Skip to content

SDK packages

The Ratify Protocol ships reference SDKs in five languages. All five are byte-for-byte interoperable — they produce identical canonical JSON, identical hybrid signatures, and pass the same 79-fixture conformance suite.

LanguageRegistryPackageVersionInstall
Gopkg.go.devgithub.com/identities-ai/ratify-protocolv1.0.0-alpha.20go get github.com/identities-ai/[email protected]
TypeScriptnpm@identities-ai/ratify-protocol1.0.0-alpha.20npm install @identities-ai/[email protected]
PythonPyPIratify-protocol1.0.0a20pip install ratify-protocol==1.0.0a20
Rustcrates.ioratify-protocol1.0.0-alpha.20cargo add [email protected]
C/C++GitHub Releaseslibratify_c.a / libratify_c.so1.0.0-alpha.20Download pre-built archive or build from source — see C/C++ SDK

All five versions are released atomically — every tagged release of the protocol contains the same version of every SDK. A consumer using v1.0.0-alpha.20 in Go and v1.0.0-alpha.20 in Python is guaranteed to produce and verify byte-identical bundles.

Three releases published since alpha.17. No canonical bytes, fixture contents, wire format or verifier behavior change in any of them, the protocol version remains 1, and all 79 fixtures are byte-identical to alpha.17.

C SDK: context-bound proof bundles (alpha.20). ratify_proof_bundle_create_with_context builds a ProofBundle carrying a 32-byte session context, so a C caller can now produce a context-bound proof rather than only verify one. Go, Rust, Python and TypeScript already had an equivalent entry point. Both the challenge and the session context must be exactly 32 bytes. Existing symbols are unchanged, so the addition is ABI-compatible for callers already linked against alpha.19.

TypeScript: base64 decoder backtracking (alpha.19). The fallback decoder stripped trailing padding with an expression that backtracked polynomially, measured at 3.4 seconds for 80 000 characters. It is reachable only where Buffer is undefined, which means browsers, Deno and edge runtimes. The strip now scans backwards and is linear.

Rust and C: minimum SDK surface completed (alpha.18). Both gained the operations the published surface documents but did not expose, and the two C conformance sign-byte assertions the suite was documented to make are now actually made.

Python: time-window denial without a system time-zone database (alpha.18). Constraint evaluation denied time_window on hosts carrying no tz database, which affected Windows and slim containers on every earlier release. tzdata is now an unconditional dependency. A separate ratify-protocol-native distribution provides deterministic seed-based key generation; ratify-protocol itself remains pure Python.

A packaging and documentation release. No SDK behavior, canonical bytes or fixture contents change, and all 79 fixtures are byte-identical to alpha.16.

Python SDK dependency bound. pqcrypto 1.0.0, published 2026-08-15, changed ML-DSA-65 behavior, and hybrid signatures do not verify against it. The Python package declared pqcrypto>=0.3.4 with no upper bound, so any installation made from that date produced a verifier that rejected valid signatures, including the canonical fixtures. The dependency is now bounded to >=0.3.4,<1.0. No other SDK depends on pqcrypto. Anyone who installed 1.0.0a17 on or after 2026-08-15 should upgrade, or pin pqcrypto<1.0 alongside it.

Extension type namespaces (SPEC §17.7). Newly defined extension constraint types use a reverse-domain prefix controlled by the defining organization; Ratify profiles use com.ratifyprotocol.<profile>.<type>. Existing signed names, verifier behavior, SDK APIs and canonical fixture bytes are unchanged.

The resource-bound authority release. It is additive: existing signed objects remain byte-stable, and the conformance suite grows from 63 to 79 fixtures for the new constraint and bounds behavior.

Resource-bound authority (resource_path constraint, SPEC §5.7.2, §5.7.3). A delegation can now name where a scope applies, not just what it permits. A resource_path constraint binds authority to an opaque resource_id (compared by exact byte equality, never dereferenced or normalized) and an optional path_prefix under segment-boundary matching. Chain evaluation stays conjunctive, so effective authority can narrow but never widen.

Resource-identifier profiles (SPEC §5.7.4). The shared recipes that make an opaque resource_id interoperable, with a Git profile v1 and known-answer plus negative vectors. Profiles are versioned outside the core spec and invisible to parties that do not adopt them; byte-equality remains the only comparison.

Extension-constraint parameters (SPEC §5.7.1, §17.7). Parameterized extension constraints are now representable in signed certificates under a restricted, cross-language-deterministic value model. Type-only extension constraints serialize exactly as before, so existing signed certs stay byte-stable.

Input bounds (SPEC §5.1). MAX_PROOF_BUNDLE_BYTES (128 KiB, applied to the received wire representation and enforced before parsing), MAX_JSON_NESTING_DEPTH, and per-certificate scope and constraint count and length limits. Violations route to the existing invalid status.

Deeper chains. MAX_DELEGATION_CHAIN_DEPTH rises from 3 to 8 for multi-hop agent topologies. The ceiling is a wire-determinism and denial-of-service bound, not a cryptographic limit; the new input bounds cap the work that depth alone does not.

Cross-SDK hashing correctness. bundle_hash in the Python and TypeScript SDKs now canonicalizes delegation constraints by kind, so a resource_path-bound bundle produces the same digest across every SDK. A constrained cross-SDK vector guards against regression.

The integration-readiness release — no wire-format changes; all 63 fixtures are byte-identical to alpha.13.

Public wire codecs (TypeScript, Python). encodeProofBundle/decodeProofBundle and friends for certs, bundles, and session tokens — strict decoding (duplicate keys, out-of-domain integers, invalid UTF-8, and unknown fields are rejected), with cross-SDK round-trip parity tests. No more hand-written transport glue.

Single-use challenges (SPEC §10, normative). A ChallengeStore in every SDK makes verifier-issued challenges single-use: validated before signature work, atomically consumed after the challenge signature verifies. A captured bundle no longer replays inside the freshness window at an issuing verifier.

Streamed verification with options (SPEC §5.13). The session-token fast path now enforces a required scope, single-use challenges, and session/stream bindings through a dedicated options object in all five SDKs.

Operation and session context (SPEC §6.4.9) + Middleware Custody Profile (SPEC §15.2.1). Canonical, domain-separated constructions that bind a presentation to the verifier, workspace, agent, session, invocation, and the specific operation — and a named conformance profile for platforms whose middleware signs on behalf of hosted agents.

Vocabulary parity + honest performance docs. vocabulary()/scopeWildcards() in every SDK, and a per-SDK benchmark matrix and wire-size table replace one-size-fits-all latency claims.

A metadata and tooling release — no wire-format changes; all 63 fixtures are byte-identical to alpha.13. The canonical project description (“delegated-authority proofs for human-agent and agent-agent interactions”) now ships in every registry’s metadata and README, the npm install pin is corrected (it had lagged at alpha.10 on the npm page), and both Rust crates are clippy-clean with lint gating in CI.

Registry read binding (SPEC §13.1). The optional lookup contract behind registry-mode key discovery: GET /v1/registry/principals/{human_id} returns the principal’s current root key, the full key-rotation chain, and the optional anchor — so any registry (the managed Verify service or a third party) is interchangeable. TLS-mandatory, fail-closed resolver semantics, and explicit first-trust framing: rotation proves continuity after first trust; it never creates it.

Reference resolver. cmd/ratify-verifier gains --registry <https-url> (registry trust: operator + TLS) and --registry-pins + --registry-require-pinned (pin-plus-registry: only first-trusted principals and their rotation successors).

No-expiry sentinel. A DelegationCert whose expires_at equals NO_EXPIRY_SENTINEL = 4070908799 (2099-12-31 23:59:59 UTC) means “no expiry (until revoked)”. Display and policy code must branch on the sentinel; every SDK ships a helper (IsNoExpiry() in Go, isNoExpiry() in TypeScript, is_no_expiry() in Python and Rust, ratify_expires_at_is_no_expiry() in C). Verification is unchanged; revocation is the sole termination mechanism for such certs.

presence:represent scope (sensitive). The canonical vocabulary grows to 54 scopes: an agent may attend and interact as a direct representative of the principal. No presence:* wildcard; does not imply identity:prove. See Scopes.

Verifier scope-vocabulary validation. A cert granting a scope that is not canonical, not a wildcard, and not a custom: extension is now rejected with the new identity status invalid_scope, before any effective-scope arithmetic.

Conformance suite grows to 63 canonical fixtures — four new fixtures pin the additions above; all pre-existing fixtures are byte-identical to the previous release.

C/C++ SDK — full conformance-suite parity. All canonical fixture kinds now pass through the C ABI: verify, scope, revocation, revocation_push, key_rotation, session_token, transaction_receipt, and witness_entry. 13 new exported functions added to the C API (ratify_*_sign_bytes_hex, ratify_verify_streamed_turn, ratify_transaction_receipt_verify_full). Pre-built libraries for common targets now published as GitHub Release assets — no Rust toolchain required to use the C SDK.

SDK README overhaul — consistent structure and cross-language framing across all five SDKs. npm Trusted Publisher (OIDC) configured; @identities-ai/ratify-protocol now available directly from npm.

C/C++ SDKlibratify_c.a (static) and libratify_c.so (shared) with a cbindgen-generated ratify.h header (includes C++ extern "C" guards). Supports embedded RTOS targets (FreeRTOS, Zephyr) via custom entropy.

Provider hooks (SPEC §17) — the verifier’s deterministic core is bracketed by pluggable hooks:

  • RevocationProvider / PolicyProvider / AuditProvider (§17.1–§17.3)
  • VerificationReceipt (§17.5) — verifier-signed, hash-chained audit attestation
  • PolicyVerdict (§17.6) — HMAC-bound cached policy decision
  • ConstraintEvaluator registry (§17.7) — pluggable extension constraint evaluators
  • AnchorResolver (§17.8) — identity-bound receipt anchoring
  • IsRevoked closure deprecated (§17.1 RevocationProvider is the replacement; removal scheduled for v1.0.0-beta.1)

See Provider architecture for the full picture.

Verifying you’ve installed the real thing

Section titled “Verifying you’ve installed the real thing”

Each registry exposes the source of every published version. To prove the package you installed matches the repo:

Terminal window
# Python — PyPI lets you download the wheel directly
pip download ratify-protocol==1.0.0a20 --no-deps -d /tmp
# Compare the wheel's sha256 against the GitHub Release's sha256
# Rust — crates.io publishes via the same git tag
cargo install --version 1.0.0-alpha.20 --git https://github.com/identities-ai/ratify-protocol
# Then run cargo test in the install dir → all 79 fixtures pass
# Go — the Go module proxy serves directly from the GitHub tag
GOPROXY=https://proxy.golang.org go get github.com/identities-ai/[email protected]
# pkg.go.dev shows the source view linked back to the GitHub repo
# C/C++ — build from source or download pre-built libraries from GitHub Releases
git clone https://github.com/identities-ai/ratify-protocol
cd ratify-protocol/sdks/c
cargo build --release
# → target/release/libratify_c.a + libratify_c.so + include/ratify.h

The conformance fixtures are the practical interop check: any SDK passing all 79 produces the same canonical bytes as every other SDK at that version.

All five SDKs are published from a single CI pipeline triggered by a v* tag:

git tag v1.0.0-alpha.20
git push origin v1.0.0-alpha.20
┌─────────────────────────────────────────────┐
│ .github/workflows/release.yml fires │
│ │
│ 1. gate-tests: │
│ - Go tests + race detector │
│ - Test vectors regenerate byte-ident. │
│ - Release-sync (versions aligned) │
│ - TS conformance (79 fixtures) │
│ - Python conformance (79 fixtures) │
│ - Rust conformance (79 fixtures) │
│ - C conformance (79 fixtures) │
│ - Tag ↔ SDK version coherence │
│ │
│ 2. If all pass: │
│ - publish-pypi (Trusted Publisher OIDC) │
│ - publish-crates (token) │
│ - publish-npm (token, when enabled) │
│ - publish-go (pkg.go.dev auto-warm) │
│ - github-release (notes + testvectors │
│ + pre-built C libraries) │
└─────────────────────────────────────────────┘

Any conformance failure blocks the entire release. There is no “publish Python but skip the broken Rust” path — versions stay aligned by design.

See the protocol repo’s docs/RELEASES.md for the full release process and recovery procedures.

During the alpha series, fixture bytes may change between versions. Each alpha release documents the diff in the GitHub Release notes. Consumers pinning to alpha.6 and alpha.7 should expect a small migration.

After 1.0.0 stable ships, fixture bytes are frozen for the entire v1 lifetime. Minor and patch releases add new optional fields and new scopes without changing existing byte representations.