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
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— usesJSON.stringify(proof)python/numbersprotocol_capture/crypto.py:71— usesjson.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 usesjson.dumpswith explicit compact separators. Neither SDK sorts keys deterministically. If a user signs with one SDK and verifies with another, any serialization difference produces a differentintegritySha, causing silent signature verification failure.Additionally, in
ts/src/client.ts:257, the proof is re-serialized independently from the hash computation atcrypto.ts:44, creating a fragile coupling where two separateJSON.stringifycalls must produce identical output.Suggested fix:
JSON.stringify(proof, Object.keys(proof).sort())in TS,json.dumps(..., sort_keys=True)in Python).2. Python httpx.Client Resource Leak Risk
File:
python/numbersprotocol_capture/client.py:131-159The
Capture.__init__createsself._client = httpx.Client(timeout=30.0)but there is no__del__finalizer. Users who do not use the context manager (withstatement) and never call.close()leak the connection pool. There is noResourceWarningor documentation warning about this.Suggested fix:
__del__that callsself._client.close()as a safety net.ResourceWarningif the client is garbage-collected without being closed.3. TypeScript
fetch()Calls Lack Network Error WrappingFiles:
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'sNetworkErrortype. When DNS resolution fails, TLS handshake fails, or the network is down,fetch()throws a rawTypeError(browsers) or genericError(Node.js). By contrast, the Python SDK correctly catcheshttpx.RequestErrorand wraps it.Suggested fix:
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