Skip to content

Fix cross-SDK JSON serialization mismatch, httpx resource leak, and missing network error handling#28

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/fix-json-serialization-mismatch
Draft

Fix cross-SDK JSON serialization mismatch, httpx resource leak, and missing network error handling#28
Copilot wants to merge 2 commits intomainfrom
copilot/fix-json-serialization-mismatch

Conversation

Copy link

Copilot AI commented Mar 15, 2026

Three production reliability issues: silent cross-SDK signature verification failures caused by non-deterministic JSON key ordering, connection pool exhaustion from unheld httpx.Client references, and unhandled TypeError/Error escaping the SDK's error hierarchy on network failure.

JSON serialization consistency

Both SDKs now serialize integrity proofs with sorted keys and compact separators, guaranteeing identical integritySha regardless of which SDK signs or verifies.

TypeScript (crypto.ts): new serializeProof() helper used for both hashing and the form payload, eliminating the fragile double-JSON.stringify coupling:

export function serializeProof(proof: IntegrityProof): string {
  return JSON.stringify(proof, Object.keys(proof).sort())
}

Python (crypto.py): equivalent _serialize_proof() helper used in sign_integrity_proof() and reused in client.py for the signed_metadata field:

def _serialize_proof(proof_dict: dict) -> str:
    return json.dumps(proof_dict, sort_keys=True, separators=(",", ":"))

Both now produce {"asset_mime_type":…,"created_at":…,"proof_hash":…}.

Python httpx resource leak

Added __del__ to Capture as a safety net for callers that don't use the context manager or call .close() explicitly:

def __del__(self) -> None:
    try:
        self._client.close()
    except Exception:
        pass

TypeScript fetch network error wrapping

All five fetch() call sites (request, getHistory, getAssetTree, searchAsset, searchNft) now catch transport-level failures and rethrow as NetworkError, matching the Python SDK's existing httpx.RequestError handling:

try {
  response = await fetch(url, { method, headers, body: requestBody })
} catch (error) {
  throw new NetworkError(
    `Network error: ${error instanceof Error ? error.message : String(error)}`
  )
}
Original prompt

This section details on the original issue you should resolve

<issue_title>[Feature][High] Fix cross-SDK JSON serialization mismatch, httpx resource leak, and missing network error handling</issue_title>
<issue_description>## Summary

Three high-priority correctness and reliability issues that affect SDK interoperability and production stability.

1. JSON Serialization Inconsistency in Integrity Proof Signing (Both SDKs)

Files:

  • ts/src/crypto.ts:44 — uses JSON.stringify(proof)
  • python/numbersprotocol_capture/crypto.py:71 — uses json.dumps(proof_dict, separators=(",", ":"))

The integrity SHA is computed by hashing the JSON-serialized proof. The TypeScript SDK uses JSON.stringify(proof) while the Python SDK uses json.dumps with explicit compact separators. Neither SDK sorts keys deterministically. If a user signs with one SDK and verifies with another, any serialization difference produces a different integritySha, causing silent signature verification failure.

Additionally, in ts/src/client.ts:257, the proof is re-serialized independently from the hash computation at crypto.ts:44, creating a fragile coupling where two separate JSON.stringify calls must produce identical output.

Suggested fix:

  • Both SDKs: Sort keys explicitly (JSON.stringify(proof, Object.keys(proof).sort()) in TS, json.dumps(..., sort_keys=True) in Python).
  • Serialize the proof once and reuse the serialized string for both hashing and the form payload.

2. Python httpx.Client Resource Leak Risk

File: python/numbersprotocol_capture/client.py:131-159

The Capture.__init__ creates self._client = httpx.Client(timeout=30.0) but there is no __del__ finalizer. Users who do not use the context manager (with statement) and never call .close() leak the connection pool. There is no ResourceWarning or documentation warning about this.

Suggested fix:

  • Add __del__ that calls self._client.close() as a safety net.
  • Alternatively, use lazy initialization (create httpx.Client on first request).
  • At minimum, emit a ResourceWarning if the client is garbage-collected without being closed.

3. TypeScript fetch() Calls Lack Network Error Wrapping

Files:

  • ts/src/client.ts:176 (request method)
  • ts/src/client.ts:374 (getHistory)
  • ts/src/client.ts:430 (getAssetTree)
  • ts/src/client.ts:520 (searchAsset)
  • ts/src/client.ts:576 (searchNft)

None of the five fetch() call sites wrap network errors in the SDK's NetworkError type. When DNS resolution fails, TLS handshake fails, or the network is down, fetch() throws a raw TypeError (browsers) or generic Error (Node.js). By contrast, the Python SDK correctly catches httpx.RequestError and wraps it.

Suggested fix:

try {
  const response = await fetch(url, { method, headers, body });
} catch (error) {
  throw new NetworkError(`Network error: ${error instanceof Error ? error.message : error}`);
}

Apply this consistently across all five call sites.


Impact: Finding 1 could cause silent cross-SDK signature verification failures in production. Finding 2 causes connection pool exhaustion in long-running applications. Finding 3 causes unhandled promise rejections and poor error diagnostics.

Generated by Health Monitor with Omni</issue_description>

Comments on the Issue (you are @copilot in this section)


📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

…etwork error wrapping

Co-authored-by: numbers-official <181934381+numbers-official@users.noreply.github.com>
Copilot AI changed the title [WIP] [Feature] Fix cross-SDK JSON serialization mismatch, httpx resource leak, and missing network error handling Fix cross-SDK JSON serialization mismatch, httpx resource leak, and missing network error handling Mar 15, 2026
Copilot AI requested a review from numbers-official March 15, 2026 14:16
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.

[Feature][High] Fix cross-SDK JSON serialization mismatch, httpx resource leak, and missing network error handling

2 participants