Decision record — one core, thin clients
Accepted: one verifying core, in Python or as your own service behind a frozen OpenAPI contract; other languages get thin clients, never a rewrite.
Context
Status: Accepted (2026-07-20) · depends on the specification’s verifier obligations, presentation rules, decision records, paid-verification permission, single-core rule and trust boundaries · Updated 2026-10-04: audit wording.
The Python surface of the verifier SDK is fixed (one entrypoint, five infrastructure ports) and its packaging is decided (see the packaging record: platform packages with the Rust engine compiled in). But many verifier agencies build their backends outside Python, and TypeScript/Node and PHP are common in web-facing agency stacks; nothing yet said what a TypeScript or PHP "MintID SDK" is.
The dangerous default is that each becomes a port of the validation entrypoint: three implementations of the nine acceptance conditions, three state-proof verifiers, three places for the engine release 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 in production, and it triples the prebuilt-binary matrix. Nothing today demonstrates demand that justifies it. It re-enters only on demonstrated integrator need, through its own design record.
Option C — idiomatic reimplementation per language (rejected permanently)
The "native SDK" each ecosystem superficially expects — and three audit surfaces that drift independently. Every new implementation of consensus-relevant cryptography becomes an audit item, a scheduled milestone whose findings are published, and this option adds two of them. The trust-boundary rule becomes a promise instead of a property, and a bug fixed in one binding survives in the others.
| A: thin clients | B: native bindings | C: reimplementation | |
|---|---|---|---|
| Crypto implementations | 1 | 1 (after Rust migration) | 3 |
| Audit surface added | none | foreign-function bridge ×2 | full pipeline ×2 |
| In-process latency | Python only | all | all |
| Fourth language later | trivial | binding + binaries | full 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 under the SDK’s semver policy — major on any change to decision semantics or the reason-code vocabulary — and frozen before the first client ships (see the verifier service contract record).
- 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.
- Idiomatic packaging in each language — for TypeScript, an ES module with type definitions — with framework bridges as separate optional packages, never in the core client.
Development order: ① the Python embedded SDK (the reference the vectors derive from); ② the OpenAPI contract, the service-mode deployable and the conformance vectors — the load-bearing new artifact; ③ the TypeScript client. All three exist. Clients in further languages are added only as integrator demand appears, against a surface the TypeScript work has already hardened.
Consequences
We commit to owning an HTTP compatibility surface and a vector suite alongside the packaging pipeline. In exchange, integrators in any language can never end up running verification logic outside the single pipeline through a supported channel: every decision an agency accepts traverses the one pipeline that the scheduled audits will cover, whatever language its backend speaks.