Skip to content

feat(openapi): Int64String codec for 64-bit ids over JSON#12

Merged
AcidSailor merged 3 commits into
mainfrom
feat/int64-string-schema
Jul 14, 2026
Merged

feat(openapi): Int64String codec for 64-bit ids over JSON#12
AcidSailor merged 3 commits into
mainfrom
feat/int64-string-schema

Conversation

@AcidSailor

Copy link
Copy Markdown
Owner

Why

64-bit ids (e.g. Alor order ids ~2e18) exceed float64's exact-integer range
(2^53 ≈ 9e15). A JavaScript-based MCP host parses a JSON number into a
float64, truncating the low digits before the value reaches the Go server.
The standard fix (protobuf JSON, Stripe, Twitter snowflake) is to carry 64-bit
ids as JSON strings.

What

New in openapi:

  • Int64String — an int64 that round-trips through JSON as a quoted
    decimal string. Decode is string-only and rejects bare numbers (a number
    is already truncated by the time we see it — failing loud beats acting on the
    wrong id). MarshalJSON emits the quoted form; Int64() accessor.
  • Int64StringSchema(desc) — the matching input schema
    ({type: string, pattern: ^-?[0-9]+$}), preserving the description.
  • StringifyIntParam(schema, name) — rewrites an already-assembled object
    schema's integer id property to the string form; no-op if absent.

Tests

8 new unit tests: exact 2011734313187604080 round-trip, rejection of bare
numbers / null / non-integer strings, schema shape, param rewrite. Suite green
(130), lint clean.

First consumer: alormcp (fixes orderId/stopOrderId truncation on
replace/cancel).

🤖 Generated with Claude Code

…cases

Address PR review of the Int64String codec:

- StringifyIntParam now panics (wrapping ErrUndefined) when the named
  property is absent, matching the panic-on-unknown-name convention of the
  other openapi accessors. A silent no-op could leave a 64-bit id advertised
  as `integer` after a param rename/typo — silently reintroducing the exact
  float64 truncation this type prevents.
- Preserve the property's Title (not just Description) on rewrite; document
  that integer-only keywords (minimum, format, …) are intentionally dropped.
- Clarify that int64StringPattern is an advisory client hint and ParseInt is
  the authoritative gate (accepts leading '+', enforces the int64 range the
  regex cannot express).
- Tests: reject overflow (int64 bounds ±1) matching-the-pattern-but-not-the
  decoder; round-trip MaxInt64/MinInt64/negative/zero; reject a small bare
  number (guard is unconditional, not range-driven); assert Title preservation
  and the absent-name panic.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Drop the dead bytes.TrimSpace and manual quote guard in
UnmarshalJSON; json.Unmarshal into a string already rejects bare
numbers and non-string JSON, and the SDK strips surrounding
whitespace before the call. Removes the bytes import.

Fold positive bigID into the round-trip table and delete two tests
it subsumes (MarshalEmitsQuotedString, RoundTripIsIdentity).
@AcidSailor AcidSailor marked this pull request as ready for review July 14, 2026 12:11
@AcidSailor AcidSailor merged commit 367e60d into main Jul 14, 2026
2 checks passed
@AcidSailor AcidSailor deleted the feat/int64-string-schema branch July 14, 2026 12:11
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