Skip to content

fix: SoQL escaping, NY-timezone today, error detail - #7

Merged
noneck merged 2 commits into
mainfrom
fix/soql-escaping-and-timezone
Jul 6, 2026
Merged

fix: SoQL escaping, NY-timezone today, error detail#7
noneck merged 2 commits into
mainfrom
fix/soql-escaping-and-timezone

Conversation

@noneck

@noneck noneck commented Jul 6, 2026

Copy link
Copy Markdown
Member

Problem

From the 2026-07-06 code review (follow-up to #6):

  1. SoQL injection / unescaped quotesgetNoticesByType and getNoticesByDateRange interpolated user input into $where clauses without escaping single quotes; no client-side validation of notice types or dates.
  2. UTC "today"getOpenSolicitations used new Date().toISOString(), so between 8pm and midnight ET the UTC date is already tomorrow and same-day solicitation deadlines were wrongly dropped.
  3. Discarded error bodies — Socrata puts the useful diagnostic (e.g. "Could not parse SoQL query") in the response body, which was thrown away; errors only carried status + statusText.

Fix

  • Shared soqlString() helper (quote-doubling per SQL rules), used by every $where builder.
  • notice_type validated with z.enum mirroring the advertised tool enum; both now derive from a single exported NOTICE_TYPES constant. Date-range params validated as YYYY-MM-DD.
  • nyToday() computes today's date in America/New_York via Intl.DateTimeFormat('en-CA'); accepts an injected clock for testing.
  • Failed responses now include the response body, truncated to 300 chars, in the thrown error.

Live verification (read-only, 2026-07-06)

  • $group=type_of_notice_description returned exactly the 10 values already hardcoded in the enum and the in (...) lists (Award 52,880; Solicitation 45,031; … Intent to Negotiate 1), plus ~956k rows with a null type. No mismatches; list pinned in a dated code comment.
  • All start_date values are midnight (date_extract_hh/mm != 0 → 0 rows), so the <= endDate upper bound already includes the full end day. Documented in a code comment instead of changing the comparison.

Test plan (already run, green)

  • npm run build — clean.
  • npm test — 8/8 pass: quote-escaping regressions for type/agency/date-range (including an injection-shaped input), nyToday with injected clocks across EDT/EST boundaries, error-body inclusion + 300-char truncation, plus the existing fix: double-encoded SoQL wildcard broke agency search #6 encoding test.

🤖 Generated with Claude Code

noneck and others added 2 commits July 6, 2026 09:23
- Add soqlString() helper (quote-doubling) and use it in every $where
  builder: getNoticesByType, getNoticesByAgency, getNoticesByDateRange.
- Validate notice_type with z.enum (mirrors the advertised tool enum,
  now derived from a single NOTICE_TYPES constant) and date params as
  YYYY-MM-DD.
- getOpenSolicitations: compute "today" in America/New_York (nyToday())
  instead of UTC, which dropped same-day deadlines after 8pm ET.
- Include the (truncated, 300-char) Socrata error body in thrown errors.
- Live-verified 2026-07-06: dataset's distinct type_of_notice_description
  values exactly match the hardcoded lists/enum (10 values, plus null
  rows); all start_date values are midnight, so the <= end bound is
  correct (documented in code).
- Tests: escaping regressions, injected-clock NY-date checks (EDT/EST),
  error-body inclusion + truncation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…refresh

- Bump package.json/lockfile to 1.0.2.
- Server reads its version from package.json via createRequire instead of
  a hardcoded string.
- CHANGELOG: move Unreleased items into 1.0.2 (double-encoding fix #6,
  SoQL escaping + enum enforcement + NY-timezone today + error detail #7,
  hono bump #4, CI #3, release automation #8).
- README: Claude Code config updated to .mcp.json / claude mcp add;
  add npm test instructions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@noneck
noneck force-pushed the fix/soql-escaping-and-timezone branch from 8bbb393 to b9552cc Compare July 6, 2026 13:25
@noneck
noneck merged commit 4d97e49 into main Jul 6, 2026
2 checks passed
@noneck
noneck deleted the fix/soql-escaping-and-timezone branch July 6, 2026 13:25
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