Hyperledger Identus SDK for Rust
Chain-neutral Rust foundations for decentralized identity, verifiable credentials, and wallet products.
Pre-release software: the active
developline and0.1.0-rc.1trains are experimental. A registry receipt—not this handbook—proves whether a crate is published. No crate is production-supported, certified, or a final SemVer commitment.
This handbook answers three practical questions:
- What reusable capabilities belong in SDK-Rust?
- Why are the crypto foundation and DID capabilities separate release trains?
- What evidence and human decisions remain before each candidate can advance?
The short version
| Crate | One responsibility | Deliberately outside |
|---|---|---|
identus-derive | Generate recurring validated-newtype and port-marker scaffolding at compile time. | Runtime SSI, protocol, chain, storage, and product policy. |
identus-core | Provide chain-neutral errors, time, URL, component metadata, and foundational capability types. | Cryptographic algorithms, DID methods, transports, custody, and wallet policy. |
identus-crypto | Provide reusable bytes-in/bytes-out cryptographic primitives and explicit entropy injection. | Key custody, hardware/KMS policy, JOSE/protocol policy, ledgers, and wallet decisions. |
The dependency direction is intentional: crypto builds on core; core uses the derive tooling; neither foundation may depend on a blockchain, wallet product, or downstream repository.
The next independent train is candidate-only. identus-did supplies generic
DID values, document models, and resolver ports. identus-did-resolver-http
is the optional Axum host adapter. It adds no DID method, ledger, chain, wallet,
or product policy.
Navigate
- Start here for project maturity and terminology.
- The first crypto release train for the initial product decision and protected publication mechanics.
- DID candidate train for the source-only review surface.
- Crates for focused responsibilities and examples.
- Architecture for dependency and ownership diagrams.
- Release readiness for the live approval checklist.
- Adoption for exact-revision source evaluation before release.
Start here
SDK-Rust is the generic Rust foundation shared by Identus ecosystem products. It is not a wallet application, blockchain SDK, cloud service, or umbrella that automatically owns every SSI protocol.
Ownership rule
Reusable, chain-neutral domain primitives, cryptographic utilities, protocol engines, ports, validation, and conformance evidence belong in SDK-Rust. Method, ledger, runtime, custody, consent, trust, persistence, user experience, deployment, and certification policy remain with their owning downstream.
That distinction allows Midnight Identity, NeoPRISM/Cardano, Lace ID Portal, Oxid, and future products to share foundations without forcing one chain or product model into the others.
Maturity vocabulary
| Term | Meaning here |
|---|---|
| Implemented | Code and tests exist; the public surface may still change. |
| Candidate | A reproducible artifact is available for review; publication status is proven only by its registry receipt. |
Experimental 0.x | SemVer applies with an explicit migration policy and support window. |
| Supported | The documented compiler, targets, features, and support period are an effective promise. |
| Certified | An external assessment or certification exists; tests alone never imply this. |
The first three packages—identus-derive, identus-core, and
identus-crypto—are release-activated 0.1.0-rc.1 packages. The independent
identus-did and identus-did-resolver-http train is candidate-only: its
release-shaped archives are prepared in an isolated temporary workspace, but
its canonical manifests remain version 0.0.0 with publish = false. Every
other workspace package remains 0.0.0, unpublished, and outside either
candidate closure.
Branches
developis the protected integration and documentation source.mainis intentionally reserved and is not populated by site publication.- Releases require a separately approved exact revision and protected process.
For the repository-level contract, see Governance, constraints, and the release policy.
The first crypto release train
The first published prerelease is a three-package closure at 0.1.0-rc.1:
identus-crypto =0.1.0-rc.1
├── identus-core =0.1.0-rc.1
└── identus-derive =0.1.0-rc.1
identus-core =0.1.0-rc.1
└── identus-derive =0.1.0-rc.1
identus-derive is included because it generates foundational type behavior at
compile time. identus-core gives the crypto crate stable chain-neutral error,
metadata, URL, and clock contracts. identus-crypto is the independently useful
consumer capability that justified preparing the closure first.
Why not release the whole monorepo?
The workspace also contains implemented experimental components and quarantined placeholders. Releasing all of them together would convert package presence into accidental API, support, and namespace promises. The isolated train keeps the first review cohesive. DID follows its own candidate-only train; credentials, protocols, bindings, and wallet ports remain on their own evidence-driven timelines.
The separate DID candidate train reuses the released foundation without changing this train’s immutable tag or publication receipt.
Candidate and publication mechanics
The three canonical package manifests carry 0.1.0-rc.1; every unrelated
workspace member retains the 0.0.0, publish = false default. The candidate
tool creates a temporary three-member workspace, uses exact internal
requirements, and assembles every Cargo archive twice. It verifies normalized
contents, extracted archive closure, feature profiles, public API, SemVer,
SBOMs, checksums, tool versions, source identity, and limitations.
Candidate preparation is deliberately not publication. The descriptor
states publication = "release-gated": upload occurs only from a signed exact
tag through the protected crates-io environment, with an independent
maintainer approval and an immutable publication receipt. The namespace-
creating train uses a short-lived bootstrap token; every later train uses
crates.io trusted publishing through OIDC.
The credential-bearing job repeats the signed-tag, exact-SHA, and protected
develop ancestry checks after environment approval. Candidate artifacts are
scoped to the workflow run rather than an individual attempt, so a failed job
can be retried without rebuilding or substituting evidence. Existing packages
and release assets are reused only when their checksums and release identity
match exactly; disagreement fails closed.
Read ADR 0134, ADR 0113, and the candidate descriptor for the executable contract.
DID candidate train
M5 prepares two chain-neutral packages as an independent 0.1.0-rc.1
candidate:
identus-did-resolver-http =0.1.0-rc.1
├── identus-did =0.1.0-rc.1
└── identus-core =0.1.0-rc.1
identus-did =0.1.0-rc.1
├── identus-core =0.1.0-rc.1
└── identus-derive =0.1.0-rc.1 (build-time)
Responsibilities and boundary
| Package | Owns | Does not own |
|---|---|---|
identus-did | Validated DID and DID URL values, DID documents, verification methods, services, resolver-facing models, and generic resolver ports. | DID methods, ledger access, networking, persistence, key custody, trust, consent, or wallet policy. |
identus-did-resolver-http | Axum request/response mapping, DID resolution content negotiation, and optional openapi schema types. | A resolver implementation, DID method, deployment topology, authentication, rate limiting, or product policy. |
The HTTP package is an optional host adapter, not a required facade. Consumers
that need only domain values or implement their own transport select
identus-did directly. DID method and chain adapters depend on the generic
ports from outside this candidate boundary.
Candidate state
The canonical workspace manifests are still version 0.0.0 with
publish = false. The candidate tool stages release-shaped archives in an
external scratch workspace without changing those manifests. Its reserved
future tag is identus-did-v0.1.0-rc.1; no tag, GitHub release, publication
workflow, or crates.io artifact is claimed here.
The exact protected source revision for this review is:
cda086f3e7fe72d251c1f896bccdcf5dd1bc8c16
Use the source-adoption instructions to evaluate it. A library that will itself be published to crates.io cannot retain a Git dependency and must wait for registry-published packages.
Reproducible evidence
Two clean preparations reproduced the same candidate archives and evidence:
| Evidence | identus-did SHA-256 | identus-did-resolver-http SHA-256 |
|---|---|---|
| Cargo archive | ec9ed5be2f8d716d1395cdea347ec71f19def355617579a7ad26cfc14681f7a7 | 875801cbcd2bb5b1e378ca4f84903f1f58949da7447cea7e586f172845eb8434 |
| Public API origin | 3412a7dce4b5699afda75ad5c9a0bb4f6f5fbb5cb3256e187a2d107fb26763dd | 9c432f0d0c3d5db92da3aa88aed05164aa2adf483c11be84b9239c9973179df6 |
| Normalized CycloneDX 1.5 | 371096ba00a08803548b67afcff8df15c10a228fbcd0bfbcf6297e742e475175 | 9f1734f3e400850c58dddc13ed36ea52d71050be899788ec988926b0ca1b5349 |
The committed API snapshots establish the origin for later SemVer comparison.
Because this is the first candidate, compatibility is explicitly
not-applicable-first-candidate; no self-comparison was used to manufacture a
green result. The SBOMs describe dependencies and licenses but do not replace
Cargo-deny, advisory review, provenance, or security assessment.
Primary evidence:
- DID candidate descriptor
- Release-train registry
- ADR 0153: independent train tags
- ADR 0154: first-candidate API origin
- ADR 0155: staged compiler and target matrix
- Supply-chain qualification issue #384
Compiler and target contract
| Package | Linux + macOS | Browser WASM | Android ARM64 | iOS ARM64 |
|---|---|---|---|---|
identus-did | Primary tests + MSRV compile checks | Compile-checked | Compile-checked | Compile-checked |
identus-did-resolver-http | Primary tests + MSRV compile checks | Not supported | Not supported | Not supported |
The matrix always exercises the staged 0.1.0-rc.1 sources and their exact
internal dependency versions. Portable rows use cargo check with Rust 1.98.1
and 1.89.0; they make no browser, device, simulator, binding, packaging,
performance, or certification claim. The HTTP adapter is host-only by design.
Weekly/manual slow CI produces four attempt-scoped lane receipts and accepts
their aggregate only when source revision, compiler identities, target rows,
outcomes, and staged lockfile agree.
Promotion gates
Candidate assembly and documentation do not authorize publication. The matrix implementation is tracked in #387, but only a natural or explicitly approved manual slow run at the final revision constitutes release evidence. M5 then requires an independent exact-SHA decision in #388. Administrator-owned trusted-publishing hardening remains tracked by #344.
See release readiness for the consolidated gate table.
Candidate crates
Each candidate crate has one reason to exist and a visible boundary. The separation is designed for low coupling, high cohesion, minimal feature cones, and independent future evolution.
Crypto foundation train
| Crate | Kind | Runtime dependency direction |
|---|---|---|
identus-derive | Procedural macro | Build-time only |
identus-core | Foundation values and ports | Depends on identus-derive and Serde |
identus-crypto | Cryptographic primitives | Depends on identus-core and identus-derive; algorithms are feature-gated |
The release train is not a layered facade where consumers must always import all three. A consumer normally selects the highest-level crate it needs; Cargo resolves its exact internal closure.
DID candidate train
| Crate | Kind | Runtime dependency direction |
|---|---|---|
identus-did | Generic DID domain and ports | Depends on released identus-core; uses identus-derive at build time |
identus-did-resolver-http | Optional Axum HTTP adapter | Depends on identus-did, released identus-core, and host HTTP libraries |
These two packages are candidate-only and source-evaluated. They are not
available from crates.io merely because a staged 0.1.0-rc.1 archive and
public-API origin exist. See the DID candidate review.
identus-derive
identus-derive is compile-time tooling for repetitive, security-sensitive
domain-type structure.
It owns
#[derive(Newtype)]for supported single-field string, byte, and numeric tuple structs;- generated constructors, accessors, conversions, display behavior, optional Serde integration, and fallible parsing appropriate to each category;
#[identus::port], an inert capability marker that enforces the SDK’s port-trait naming convention;- validation of generated output against forbidden unsafe constructs before tokens leave the macro.
It does not own
- business or protocol validation rules;
- a runtime object model;
- cryptography, serialization formats, storage, transport, or chains;
- arbitrary code generation for downstream convenience.
The consuming type declares its domain constraint. The macro standardizes the safe shape; it does not decide what a valid DID, credential, key, or wallet policy means.
Why it is a separate crate
Rust procedural macros compile for the build host and require a dedicated
proc-macro package. Keeping that compiler surface separate also prevents
syn, quote, and proc-macro2 from becoming runtime dependencies of SDK
consumers.
Review focus
- Diagnostics and generated public APIs are compatibility surfaces.
- Generated code must inherit the repository’s no-unsafe policy.
- Compile-fail fixtures are part of the contract, not incidental tests.
- Runtime crates should expose explicit types rather than re-exporting the macro crate as a broad facade.
identus-core
identus-core holds small chain-neutral values and capability contracts that
multiple SDK components need without depending on a protocol or product.
It owns
- stable component metadata;
- capability identifiers and error codes;
- redaction-safe
IdentusError,ErrorKind, andIdentusResultcontracts; - bounded generic URLs;
- wall and monotonic clock ports plus millisecond time/duration values.
The public error value stores static public fields. Its display form contains a stable code and public message, not secrets or internal debugging context.
It does not own
- a catch-all prelude or umbrella SDK facade;
- cryptographic algorithms or secret-bearing key types;
- DID/VC/protocol wire models;
- network clients, persistence, telemetry, trust, custody, or wallet policy;
- chain or runtime integration.
Dependency role
identus-core uses identus-derive for shared type conventions and Serde for
the bounded values that require serialization. Higher crates depend inward on
core; core must never depend outward on those components.
Example: public error boundary
use identus_core::{CapabilityId, ErrorCode, ErrorKind, IdentusError};
let error = IdentusError::public(
ErrorCode::new("invalid_input"),
ErrorKind::InvalidInput,
CapabilityId::new("example"),
"input is invalid",
);
assert_eq!(error.to_string(), "invalid_input: input is invalid");
identus-crypto
identus-crypto provides reusable primitive operations on key material. Its
contract is bytes-in/bytes-out cryptography with typed boundaries—not custody,
wallet orchestration, or protocol policy.
Capability surface
- Ed25519 signing and verification;
- X25519 key agreement material and Ed25519-to-X25519 conversion;
- secp256k1 and P-256 keys, signing, and verification;
- SHA-256/SHA-512 and supporting HMAC/PBKDF2 paths;
- BIP-39, secp256k1 BIP-32, SLIP-0010, and Cardano V2 Ed25519-BIP32;
- bounded hex, Base64URL, public JWK, JWK thumbprint, and public COSE Key representations;
- caller-injected
SecureRandomfor key generation and mnemonic creation.
Feature policy
Algorithms and encodings are feature-gated. Consumers should disable defaults and select the smallest reviewed capability cone when they do not need the full suite.
| Feature | Adds |
|---|---|
hash | SHA-256 and SHA-512 digest values/functions |
ed25519 | Ed25519 key and signature operations; public JWK support |
x25519 | X25519 keys; conversion also requires hash |
secp256k1 | K-256 key and ECDSA operations |
secp256r1 | P-256 key and ECDSA operations |
jwk / jwk-thumbprint | Bounded public JWK values and RFC 7638 thumbprints |
cose | Bounded public COSE Key values |
derivation | BIP-39, BIP-32/SLIP-0010, HMAC, and required curves |
cardano-bip32 | Cardano V2 extended Ed25519 keys |
kmp-compat | Explicit legacy KMP/Apollo interop path |
Security boundary
Secret-bearing SDK types redact diagnostics and use zeroization where their owned representation permits it. The workspace forbids first-party unsafe code. Entropy is explicit and fallible; the production adapter lives outside the primitive crate.
Consumers still own:
- non-exportable key handles and hardware/KMS integration;
- secure storage, backup, recovery, access control, and consent;
- algorithm/profile negotiation and protocol verification policy;
- side-channel and platform hardening appropriate to their threat model;
- rate, message-size, and work budgets at the calling boundary.
Example: minimal hashing
use identus_crypto::sha256;
let digest = sha256(b"bounded public input");
assert_eq!(digest.as_array().len(), 32);
Before registry publication, evaluation uses a full immutable Git revision and an explicit feature set. See Adoption.
Architecture
SDK-Rust uses an inward dependency direction: products and chain adapters may depend on generic components, while generic components cannot import product, chain, runtime, deployment, or UI policy.
The first release candidate intentionally covers only the lowest cohesive three-crate closure.
Dependency direction
Arrows mean “depends on.” Dependency direction always points toward the more stable, generic center:
- wallets, identity products, and chain families select SDK components;
- protocol/domain components select primitive foundations;
identus-cryptodepends onidentus-core;identus-coreandidentus-cryptouseidentus-deriveat compile time.
The reverse direction is forbidden. In particular, the three-crate release train cannot depend on Midnight, Compact, Cardano/PRISM, consumer repositories, wallet storage implementations, or product trust/custody policy.
This allows downstreams to evolve independently while sharing evidence-backed foundations.
Ownership boundaries
SDK-Rust owns
- generic primitives and domain values;
- reusable cryptographic operations and bounded representations;
- protocol-neutral ports and validation contracts;
- conformance and compatibility evidence attached to those surfaces.
Chain and identity repositories own
- DID method semantics and operation construction;
- ledger clients, indexing, submission, synchronization, and finality;
- Compact contracts, proving systems, and chain-native cryptosuites;
- chain deployment and operational policy.
Wallet and application products own
- key custody, secure storage, consent, account recovery, and authorization;
- trust decisions, credential selection, user experience, and telemetry;
- backend deployment, availability, privacy, and regulatory controls;
- the decision to adopt an SDK revision or release.
An SDK abstraction is reusable only when these product and chain decisions can remain outside it.
Evidence and release flow
The repository separates ordinary integration from production promotion:
- Fast line: one required Ubuntu build/lint/test/factory gate for pull
requests into
develop. - Slow line: weekly/manual target, binding, fuzz, coverage, package, performance, and platform evidence on an exact protected revision.
- Candidate gate: deterministic packages, API/SemVer review, SBOMs, checksums, provenance, source closure, consumer evidence, and documentation.
- Human release gate: one release manager and a second maintainer approve the exact receipt before a tag or registry upload.
Documentation publication is evidence before the release decision. It does not advance the candidate by itself.
Adoption before publication
Every implemented SDK-Rust package can be evaluated from source; packages that
are not published require this channel. A consumer pins the full commit
reachable from protected develop, chooses features explicitly, and commits
its lockfile.
identus-crypto = {
git = "https://github.com/hyperledger-identus/sdk-rust",
rev = "FULL_40_HEX_REVIEWED_COMMIT",
default-features = false,
features = [ "hash" ],
}
The placeholder must be replaced with the exact reviewed revision. Do not use
develop, a tag that does not exist, a pull-request ref, or a short SHA.
The current DID candidate may be evaluated at the exact protected merge that contains its verified candidate evidence:
identus-did = {
git = "https://github.com/hyperledger-identus/sdk-rust",
rev = "cda086f3e7fe72d251c1f896bccdcf5dd1bc8c16",
}
identus-did-resolver-http = {
git = "https://github.com/hyperledger-identus/sdk-rust",
rev = "cda086f3e7fe72d251c1f896bccdcf5dd1bc8c16",
default-features = false,
features = [ "openapi" ],
}
Select the resolver package only when the consumer needs the Axum HTTP adapter;
select openapi only when it needs generated schema support. The reserved
candidate identity identus-did-v0.1.0-rc.1 is not a created tag or a registry
receipt. Do not add a misleading version = "0.0.0" constraint.
Adoption receipt
Record:
- old and new exact SDK revisions;
- selected packages and features;
- compiler and tested targets;
- Cargo and Nix lock/hash changes;
- dependency/feature-tree delta;
- unit, conformance, integration, advisory, and license results;
- public/wire compatibility and rollback.
The first planned M3 consumer is a minimal hash-only downstream canary. It is owned and implemented entirely downstream: this repository accepts only generic evidence and does not import consumer names, primitives, or policy. NeoPRISM provides a broader source-pinned cryptography integration reference.
The crypto train’s registry receipt and the DID train’s exact source revision are different evidence channels. Source evaluation provides no crates.io checksum, stable SemVer support promise, LTS period, certification, or production warranty.
Release readiness
The first 0.1.0-rc.1 train for identus-derive, identus-core, and
identus-crypto was published from approved source
21cfc28321f76f1d14a2483d536d302017674a18. Final 0.1.0 is not implied by
that prerelease.
M3 release record
| Gate | Status | Evidence owner |
|---|---|---|
| Reproducible isolated candidate | Published from the approved exact candidate | release v0.1.0-rc.1, ADRs 0113/0134 |
| Functional cryptography foundation | Complete within its recorded limitations | #286 |
| Public architecture/release handbook | Deployed | #324 |
| Durable crate names and first-publish bootstrap | Published; tokenless ownership/recovery hardening remains open | #3, #344 |
| Release compiler/support matrix | Complete for the published candidate | #325, ADR 0133 |
| Independent downstream canary | Exact-source canary green; downstream registry refresh remains externally owned | #326 |
| Natural weekly slow evidence | Complete at 19d0362038c3f2af6898624ea04347e3cd4648f7 | run 35555024293 |
| Exact candidate slow receipt | Complete for the published source | run 35887204030 |
| Two-person approval and protected publication | Complete; bootstrap publication receipt retained | run 35990705278, #326 |
Approval questions
Engineers reviewing later crypto trains should reuse these questions:
- Are the three crate responsibilities cohesive and appropriately separated?
- Is the public API small enough for an experimental SemVer commitment?
- Does the compiler/target promise match consumer needs and maintenance cost?
- Is the selected dependency and unsafe/native cone acceptable?
- Can a downstream adopt or reject the candidate without tribal knowledge?
- Is any release blocker absent from the evidence table?
The approval and publication record is issue #326. That issue remains open for post-bootstrap hardening, not because the first publication is unapproved. Future approval must again bind an exact source revision and candidate receipt; it cannot be inferred from this page or from a green documentation deployment.
M5 DID candidate status
The separate M5 target is 0.1.0-rc.1 for identus-did and
identus-did-resolver-http. It is candidate-only and has no publication
workflow or registry claim.
| Gate | Status | Evidence owner |
|---|---|---|
| Independent train identity and deterministic archives | Complete | #382, ADR 0153 |
| Public API origins and normalized CycloneDX evidence | Complete | #384, ADR 0154 |
| Engineer-facing architecture and adoption handbook | Implemented in this source revision; deployment receipt remains on the issue | #386 |
| Rust/target qualification | Open | #387 |
| Final exact-SHA candidate approval | Open; follows all prior gates | #388 |
| Trusted-publishing administration | Separate administrator-owned hardening | #344 |
Reviewers should start with the DID candidate train. A green site build proves documentation integrity only; it does not complete the open target, approval, registry, tag, or publication gates.
Governance and contribution
SDK-Rust is AI-first but evidence-gated. Agents may plan, implement, review,
push, and merge routine issue-linked work into protected develop after the
required checks pass. Humans retain authority over release, publication,
repository administration, security disclosure, legal-risk acceptance, and
promotion to main.
Specification-driven flow
issue → research → constraints → OpenSpec contract → preflight
→ implementation → verification → review → protected develop
→ production evidence → human release decision
Important repository references:
- Contributing
- Governance
- Security
- Release policy
- AI Software Factory
- Architecture blueprint
- Constraints and limitations
Documentation changes use the same issue, OpenSpec, signed/DCO commit, local review, exact-head CI, and protected merge controls as code changes.
Current limitations
The handbook is intentionally explicit about what has not been proven.
- Only
identus-derive,identus-core, andidentus-cryptoare activated for the protected0.1.0-rc.1crates.io train; use its registry receipt to determine live publication state. identus-didandidentus-did-resolver-httphave isolated, reproducible0.1.0-rc.1candidate archives but no crates.io release. Their canonical manifests remain0.0.0withpublish = false; evaluate them only by exact source revision.- Every package outside those two train closures also remains
0.0.0withpublish = false. - Rust 1.89.0 is the
0.1.xrelease MSRV; Rust 1.98.1 remains the primary and compatibility-etalon compiler. - WASM, iOS, and Android cryptography evidence is currently compile-oriented; it is not a blanket browser/device/runtime support claim.
- Experimental DID language-binding evidence does not automatically support the crypto or DID release train on those platforms.
- DID candidate API snapshots are a diffable compatibility origin, not a stable API promise. Candidate SBOMs are dependency evidence, not an advisory scan, signed provenance, vulnerability-free claim, or certification.
- Test vectors, fuzzing, coverage, static analysis, and review reduce risk but are not security or compliance certification.
- The SDK does not provide key custody, hardware/KMS management, secure wallet storage, trust policy, consent, chain integration, or product operations.
- Consumer adoption remains independently owned and reversible.
- Apollo deprecation and downstream duplicate removal require later releases, adoption evidence, and maintainer governance.
The machine-readable constraint index and component evidence remain normative: