Blog · architecture

Implementing clients: where the rubber meets the road

The multi-language strategy behind the MintID SDKs is decided and locked into the spec: one audited verification core, embedded in Python — and TypeScript and PHP clients that carry no cryptography and no policy, built against a verification service you host yourself. Why thin clients are the strongest guarantee we could ship.

When we announced the MintID SDKs — TypeScript, PHP and Python, in development now — we described what ships inside every binding: the same acceptance checks, the same ten-second proof lifetime, zero policy knobs. What we hadn't yet published is how three languages can carry one guarantee. That decision is now made and locked into the spec, and it is worth explaining, because the obvious way to build multi-language SDKs is a security mistake.

The obvious way is wrong

The obvious way is to rewrite the verification pipeline in each language: a TypeScript implementation for Node shops, a PHP implementation for the commercial web, a Python implementation for the data stacks. Every rewrite is a fresh chance to get a check subtly wrong — a different cryptographic library with different edge cases, a different clock behaviour, a different idea of what "expired" means a millisecond either side of the boundary. Three implementations means three attack surfaces, three audits that can disagree, and divergence that compounds with every bugfix that lands in one language first.

So the spec now says it plainly: the verification pipeline exists in exactly one implementation — the audited core — and it is never rewritten per language. Per-language reimplementation isn't deferred; it is rejected permanently.

Python embeds; TypeScript and PHP delegate

Python is the language the core is packaged for directly: the Python SDK embeds the audited pipeline in your backend, the way the verifier pages have always described embedding.

The TypeScript and PHP SDKs are deliberately thin clients. They issue challenges and delegate every decision to a verification service the verifier runs itself, next to its own backend — the same audited core, running as a service inside the agency's own infrastructure. The clients contain no cryptography and no policy. That is the whole point: there is nothing in them that could ever weaken a check. A thin client cannot skip an acceptance condition, stretch a lifetime or mis-verify a proof, because it never verifies anything — its self-hosted service does.

Note what this is not: it is not MintID hosting verification for you. The embedded, not hosted principle stands unchanged — there is no central endpoint and no API of ours in the path. The service mode is your deployment, on your machines, holding your keys. Keys and challenge issuance stay server-side in every configuration, and none of the SDKs is a browser artifact.

One conformance suite for everyone

Thin clients only give the same guarantee as embedding if you can prove the whole chain behaves identically — so every SDK, in every language, must pass one shared conformance suite before release: the same challenges, the same responses, the same expected decisions and reason codes. A verifier gets the same answer whether its backend speaks Python, TypeScript or PHP. The suite is not a courtesy; under the spec, no SDK ships without passing it.

Where the rubber meets the road

Architecture decisions are cheap until something has to be built in order. Ours is fixed: Python first, because it packages the core itself; then the service contract the clients are built against, frozen and versioned as a first-class artifact; then the TypeScript client; then PHP. Building the clients against a frozen contract — rather than against a moving core — is what makes "thin" a property that holds, instead of a diagram that erodes.

Everything here describes work in development, not packages you can download today — distribution is still the decision we haven't announced. What has changed is that the shape is no longer open: one verified implementation, consumed from Python, TypeScript or PHP, never rewritten per language. The acceptance rules stay where the protocol put them — fixed by the spec, not by the integrator, in any language you call them from.

One pipeline, whatever you run

Embed the core in Python, or point a thin TypeScript or PHP client at your own verification service. The SDKs are in development — integration starts as a design-partner conversation today.