Skip to content

refactor(serve): simplify parsePositiveInt (drop type-blind catch + redundant trim)#80

Merged
abpai merged 1 commit into
mainfrom
cleanup-parse-positive-int
Jun 23, 2026
Merged

refactor(serve): simplify parsePositiveInt (drop type-blind catch + redundant trim)#80
abpai merged 1 commit into
mainfrom
cleanup-parse-positive-int

Conversation

@abpai

@abpai abpai commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Cleanup of review findings F4 and F5 from the #77/#79 review. No behavior change — pure simplification.

parsePositiveInt routed a pre-trimmed string through parseBoundedInt inside a try/catch, then re-framed any thrown error as "must be a positive integer":

  • F4 — the bare catch {} was type-blind: a future non-validation throw from parseBoundedInt would be silently relabeled, hiding the real fault (exception-as-control-flow).
  • F5parseBoundedInt re-trimmed the already-trimmed string.

Now resolves directly through the shared parseDecimalDigits primitive (trims once, caps at MAX_SAFE_INTEGER) with an inline >= 1 check. No try/catch, so there's no catch to mask anything, and no re-trim round-trip.

Behavior preserved

  • Error code (INVALID_ARGUMENT) and message (<field> must be a positive integer (received '<value>')) unchanged.
  • Accept/reject identical: parseDecimalDigits already returns null past MAX_SAFE_INTEGER, so the old upper-bound check is preserved; absent/blank → undefined; <= 0, decimals, signs, hex/scientific all rejected.

Verification

bun run check clean; suite 499 pass / 27 skip / 0 fail (unchanged — pure refactor, existing parsePositiveInt tests lock the behavior).

https://claude.ai/code/session_01LQjR5poSV2M3nxt8h5hNad

…redundant trim

Review findings F4/F5 (no behavior change).

parsePositiveInt routed a pre-trimmed string through parseBoundedInt inside a
try/catch, then re-framed ANY thrown error as "must be a positive integer". Two
smells:
- F4: the bare `catch {}` was type-blind — a future non-validation throw from
  parseBoundedInt would be silently relabeled, hiding the real fault.
- F5: parseBoundedInt re-trimmed the already-trimmed string.

Resolve directly through the shared parseDecimalDigits primitive (trims once,
caps at MAX_SAFE_INTEGER) and range-check `>= 1` inline. No exception is used for
control flow, so there's no catch to mask anything, and the value is trimmed
without a round-trip. Error code/message and all accept/reject behavior are
identical (parseDecimalDigits already returns null past MAX_SAFE_INTEGER, so the
old upper-bound check is preserved). Suite 499 pass / 0 fail, check clean.

Claude-Session: https://claude.ai/code/session_01LQjR5poSV2M3nxt8h5hNad
@abpai abpai merged commit 11a8eb8 into main Jun 23, 2026
1 check passed
@abpai abpai deleted the cleanup-parse-positive-int branch June 23, 2026 17:17
abpai added a commit that referenced this pull request Jun 24, 2026
The serve-hardening and CLI work since v0.7.0 (PRs #76, #77, #78, #79) merged
without changesets, so the Release workflow had nothing to consume and the
package is still published at 0.7.0. Add the missing changesets so the next
release captures this work.

- serve-api-webhook-hardening (patch): #76 - envelope webhook-route errors plus
  tunnel / Postgres-receipt / broadcast / base-path fixes (10 defects).
- webhook-secret-fail-open (patch): #77 - single WEBHOOK_SECRET_ENV source of
  truth for the tunnel gate + stricter KANBAN_SYNC_INTERVAL_MS parsing.
- honor-default-task-column (patch): #78 - SQLite createTask honors the
  configured default task column, with first-column fallback parity with Postgres.
- strict-jira-board-id (minor): #79 - a malformed JIRA_BOARD_ID now throws
  INVALID_CONFIG instead of being silently misparsed (behavior change).

Net bump: minor -> 0.8.0. #80 (pure internal refactor) and the README link fix
are intentionally omitted as they have no user-facing change.

Claude-Session: https://claude.ai/code/session_01X9j5Rs6kXK8BuHguhy3x33
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