SDK docs · adr/0003

ADR-0003 — Multi-language strategy

Accepted: one verified core in Python; TypeScript and PHP as transport-only clients of a self-hosted service behind a frozen OpenAPI contract. Why reimplementing the pipeline per language was rejected permanently.

Context

Status: Accepted (2026-07-20) · card MINT-169 · spec refs R13, R14, R15, R18, R26, §1.1, §13, §14.4, §16

The Python surface of the verifier SDK is fixed (one entrypoint, five ports) and its packaging is decided (ADR-0002: wheels with the Rust engine compiled in). But verifier agencies overwhelmingly build their backends in ecosystems other than Python — TypeScript/Node and PHP cover the bulk of web-facing agency stacks — and nothing yet said what a TypeScript or PHP "MintID SDK" is.

The dangerous default is that each becomes a port of validate_presentation: three implementations of the nine acceptance conditions, three state-proof verifiers, three places for the engine pin to drift. The value of the SDK is the verified core; the languages are reach.

Options considered

Option A — one verified core; transport-only clients (accepted)

Python remains the only embedded SDK. Service mode is promoted from "a thin wrapper someone can deploy" to a first-class product: a versioned OpenAPI contract, a first-party deployable the agency runs next to its backend, and per-language clients that issue challenges and delegate every decision to the agency's own instance.

Option B — native bindings of the Rust core per language

True in-process verification everywhere and best latency — but it requires migrating the nine-condition orchestration from Python to Rust first, a large refactor of code that is implemented, tested and heading to audit, and it triples the prebuilt-binary matrix. Nothing today demonstrates demand that justifies it. Re-enters only on demonstrated integrator need, via its own ADR.

Option C — idiomatic reimplementation per language (rejected permanently)

The "native SDK" each ecosystem superficially expects — and three audit surfaces that drift independently. Any new consensus-relevant cryptography is a launch-blocking audit item; this option creates two more. §16 rule 6 becomes a promise instead of a property, and a bug fixed in one binding survives in the others.

A: thin clientsB: native bindingsC: reimplementation
Crypto implementations11 (after Rust migration)3
Audit surface addednoneFFI boundary ×2full pipeline ×2
In-process latencyPython onlyallall
Fourth language latertrivialbinding + binariesfull port

Decision & mechanics

Accepted (2026-07-20): Option A now; Option B only as a demand-gated future path; Option C rejected permanently. The mechanics:

  • The OpenAPI contract is the product. Versioned with the ADR-0002 semver policy — major on any change to decision semantics or the reason-code vocabulary — and frozen before the first client ships (see bIP-0001).
  • One cross-language conformance-vector suite, derived from the Python reference and run in CI by every SDK.
  • Clients carry no invariants to weaken: no lifetime parameter, no skip flags, no local nonce store, no presentation persistence.
  • Server-side only: challenge issuance and request keys never reach a browser.
  • Verifier obligations first in every quickstart: on-chain registration, verifier KYC and exact-origin control appear before the first code sample (R13).
  • Idiomatic packaging: npm (ESM + types) for TypeScript; Composer with PSR interop for PHP; framework bridges as separate optional packages, never in the core client.

Development order: ① Python embedded SDK (the reference the vectors derive from); ② OpenAPI contract + service-mode deployable + conformance vectors — the load-bearing new artifact; ③ TypeScript client; ④ PHP client, arriving against a surface the TypeScript work has already hardened.

Consequences

We commit to owning an HTTP compatibility surface and a vector suite alongside the wheel pipeline. In exchange, TypeScript and PHP integrators can never end up running unaudited verification logic through a supported channel: every decision an agency accepts traverses the one audited pipeline, whatever language their backend speaks.