Decision record — SDK packaging
Accepted: the verifier SDK ships as versioned platform packages with the proof engine compiled in at a version fixed at build time — so a substituted or drifted engine cannot arrive through any normal installation path.
Context
Status: Accepted (2026-07-21) · recorded 2026-07-19 · depends on the specification’s paid-verification permission and its trust-boundary rules
The verifier SDK is a Python package whose correctness depends on a specific release of the Rust proof engine and on byte-for-byte agreement with the chain’s state layout, checked by a published vector suite. An integrator must receive all of that as one verifiable unit: a mismatched engine or a stale state-layout assumption is a security defect, not an inconvenience. The distribution form had to be decided before the first external integrator existed.
Three constraints of the specification frame the choice: verification may also be offered as a paid off-chain service, so packaging must make both embedded and service consumption practical; no interface is trusted merely for returning well-formed data, so the cryptographic checks must not be silently substitutable; and proof verification lives in the pinned Rust engine while Python orchestrates — packaging must preserve the pin.
Options considered
Option A — versioned Python package with the engine compiled in (accepted)
Publish mintid-verifier-sdk as platform wheels, with the Rust engine compiled in as a native extension at a version fixed at build time and recorded in package metadata.
- Pros: one artifact, one version; standard
pip installexperience; the engine pin is decided at release time and not overridable by dependency resolution; platform wheels make the Rust toolchain invisible to integrators. - Cons: we own a per-platform build matrix and release engineering before the first integrator; source builds still need the Rust toolchain as a fallback.
Option B — git dependency at a tag
Zero release infrastructure and always buildable from source — but every integrator needs the Rust toolchain, the engine pin lives in build configuration where an integrator can patch it, and repository access is a bad long-term distribution channel with no artifact-level integrity story. Retained only as the interim channel for design partners until the first tagged release exists.
Option C — vendored source drop (rejected)
Works in locked-down environments, but has the worst upgrade path, makes pin substitution trivial, and duplicates the build burden onto every integrator.
| A: wheels | B: git tag | C: vendored | |
|---|---|---|---|
| Engine pin enforceable | yes (built-in) | weak | no |
| Integrator toolchain burden | none | Rust + ours | Rust + ours |
| Upgrade path | semver via pip | re-pin tag | manual |
| Works for paid-verification service operators | yes | yes | awkward |
Decision & versioning policy
Accepted: Option A, with B as the interim channel for design-partner integrators until the first tagged release exists. Versioning under Option A:
- Semver on the SDK package: major for any change to the public surface or to accepted-behavior semantics; minor for additive surface; patch otherwise.
- Package metadata records the engine release, the state-layout vector version and the specification revision built against. A release is blocked if the state-layout vectors fail against the target chain version.
Consequences
Option A commits us to a wheel-building pipeline and a release checklist — an engine pin bump is a reviewed change, never automatic. In exchange, integrators cannot end up running an unpinned or substituted proof engine through normal installation paths: substituting one becomes a deliberate, visible act outside the supported channel, which is exactly the posture the specification’s trust-boundary rules ask for.