DPG compatibility matrix
Capability claims in the UI reflect specific documented releases. These
versions are not a tested-compatible matrix — each vendor publishes
its own compatibility table. cross-stack scenarios (walt.id issues, Inji
verifies, etc.) work on a case-by-case basis; known breakage is called
out below with the workaround the verifiably-go inji-proxy applies.
Versions
| Component | Version | Source |
|---|---|---|
| walt.id Community Stack | v0.18.2 | docker.io/waltid/issuer-api, wallet-api, verifier-api |
| Inji Certify | v0.14.0 | docker.io/mosipid/inji-certify:0.14.0 |
| Inji Certify Preauth | v0.14.0 | Same image, different config for pre-auth flow |
| Inji Web (Mimoto + SPA) | v0.16.0 | mosipid/inji-web-ui:0.16.0, mosipid/mimoto:0.16.0 |
| Inji Verify (UI + service) | v0.16.0 | mosipid/inji-verify-ui:0.16.0, mosipid/inji-verify-service:0.16.0 |
| eSignet + mock-identity | v1.5.x | mosipid/esignet, mosipid/mock-identity-system |
| Keycloak | 25.x | quay.io/keycloak/keycloak |
| WSO2 Identity Server | 7.0.0 | docker.wso2.com/wso2is |
| LibreTranslate | latest | libretranslate/libretranslate |
walt.id Community Stack v0.18.2
What works end-to-end
- OID4VCI pre-authorized code flow (issuer → wallet → hold)
- OID4VCI authorization code flow (issuer → eSignet-like auth → wallet)
- Legacy OID4VP (Presentation Exchange 2.0)
- Credential formats:
w3c_vcdm_2(JWT),sd_jwt_vc(IETF),mso_mdoc
Known limitations
-
OID4VP v1.0 is still landing in the wallet/demo apps through v0.18.2.
Our verifier adapter uses the PE 2.0 path; switching to v1.0 means
redoingRequestPresentationandFetchPresentationResultagainst
/openid4vc/v1/*endpoints when they're available. -
OID4VP submit requires format alignment across issue→verify. Walt.id's
wallet-api only has a tested VP pipeline for the format/type pairs its
own E2E suite exercises
(waltid-services/waltid-e2e-tests/src/test/resources/presentation/*.json):jwt_vc_json↔ OpenBadge-style credentials withtypein the PDvc+sd-jwt↔ SD-JWT VCs withvctin the PD
Other combinations that walt.id's issuer CAN produce (
jwt_vc_json-ld,
ldp_vc) don't have a tested claim→present pipeline in the wallet.
Submitting a VP where the held credential's format doesn't match the
format the verifier's PD asked for causes the wallet to build an
array-formvp_tokenthat trips an internal assertion
(.jsonPrimitive.contenton aJsonArray) inside
SSIKit2WalletService.usePresentationRequest. The error surfaces as
400 "Element class kotlinx.serialization.json.JsonArray is not a JsonPrimitive". Our adapter now:- Deduplicates walt.id's credential catalog by
(Name, Std), keeping
the format walt.id has tested (jwt_vc_json for w3c_vcdm_2, vc+sd-jwt
for sd_jwt_vc) via aformatRankpreference. - Builds the verifier's
request_credentialswithvctfor SD-JWT
formats andtypeotherwise, matching walt.id's E2E fixtures.
End-to-end issue→claim→present→verify works on thejwt_vc_json + OpenBadgeCredentialpath (reproduced via curl withverificationResult: true).
-
No documented QR-on-PDF export path.
IssueAsPDFfalls back toDirectPDF: false. -
The Kotlin wallet's OID4VCI client strips
credential_definition.@context
from credential requests. When using walt.id wallet against Inji Certify,
our/inji-proxy/issuance/credentialhandler injects a sensible default
(https://www.w3.org/ns/credentials/v2).
Inji Certify v0.14.0
What works
- Issuance via both OID4VCI pre-authorized code (demo/staging) and
authorization code (production) flows. - Ed25519 signing; keys managed by MOSIP's keymanagerservice and stored
incertify.key_store.
Known bugs we work around
-
Split-kid VC vs status-list signing. Inji Certify signs regular VCs
with one kid fragment and bitstring status-list credentials with a
different kid, both derived from the same Ed25519 key. Its own
.well-known/did.jsonpublishes only one. Inji Verify's
DidWebPublicKeyResolvermatches kid strictly, so verification either
of the main VC or the status list (it needs both) fails with
PublicKeyResolutionFailedException→ the UI surfaces "Internal
Server Error".Workaround: certify-nginx's
/.well-known/did.jsonis rerouted
throughverifiably-go:/inji-proxy/.well-known/did.json. The proxy
watches every VC it forwards forproof.verificationMethodkids and
publishes all observed kids as syntheticverificationMethod
entries — all pointing at the upstreampublicKeyMultibase. The
/v1/certify/credentials/status-list/endpoint is also proxied so
status-list kids get recorded.The primary (auth-code) and pre-auth Inji Certify instances run
under separate DIDs —did:web:certify-nginxand
did:web:certify-preauth-nginxrespectively — so their signing
keys never appear in the same did.json. Before the split, both
instances claimeddid:web:certify-nginxand an unfortunate kid
collision (different Ed25519 keys, same kid fragment) stranded
whichever flow lost the merge-order race. Now each flow has its own
resolution path:/inji-proxy/.well-known/did.json(primary) and
/inji-proxy-preauth/.well-known/did.json(pre-auth), backed by
separatecertify-nginx+certify-preauth-nginxfront-ends and
separateinjidid.Primary+injidid.Preauthkid observers. -
Key rotation desyncs status-list signatures. If the Ed25519 key
rotates (any compose reset that wipeswaltid_certify-pkcs12) but
the status-list credential row survives (waltid_certify-db), every
previously-issued VC fails verification because its status-list can't
verify against the new key. Symptom:STATUS_VERIFICATION_ERROR - Invalid signature on status list VC.Workaround: for local dev, do a full reset (see
deploy.md § Full reset) so keys and the
status-list table regenerate together. In production, key rotation
would require the issuer to re-sign the status-list VCs. -
Credential-issuance endpoint proxies back to us.
certify-nginx
routesPOST /v1/certify/issuance/credentialthrough
host.docker.internal:8080/inji-proxy/issuance/credential. Without
our handler registering that route, Mimoto's credential download
gets a 404 and Inji Web shows "An Error Occurred — unable to
download the card". Our handler forwards toinji-certify:8090,
optionally patchingcredential_definition.@context. -
mDoc (ISO 18013-5) issuance is mock-only per Inji Certify's own
README at v0.14.0. Ourbackends.jsonstrips mDoc from the Farmer
catalog; the UI shows only the two LDP formats and SD-JWT. -
Two key aliases in
certify.key_aliasforCERTIFY_VC_SIGN_ED25519
(one with ref_idED25519_SIGN, one with ref_id NULL). Only the
former has a private key inkey_store; the latter acts as a
key-encryption-key wrapper. No action needed, but worth noting if you
debug the DB.
Inji Web Wallet v0.16.0
What works
- Guest + Google OIDC login
- Browser-hosted wallet (credentials live inside the SPA / Mimoto DB)
- PDF export with embedded QR for JSON-LD VCs (pixelpass compression)
Known bugs we work around
-
MIMOTO_URLhardcodes${PUBLIC_HOST}:3004. Injected at container
start intoenv.config.js. If the browser loads the SPA on a
different origin (e.g.localhost:3004) every/v1/mimoto/*XHR is
cross-origin and browsers block the responses → UI falls back to "No
Credentials found" even when Mimoto is healthy.Workaround:
UIURLin verifiably-go's backends.json points at
http://172.24.0.1:3004(matchingPUBLIC_HOSTin the shared.env),
so the redirect lands on the SPA's configured origin. -
eSignet DB caches stale
redirect_uris.seed-esignet-client.sh
returns OK onduplicate_client_idbut doesn't update — so if a
previous deploy used a different PUBLIC_HOST, eSignet rejects
/authorize withinvalid_redirect_uri. The client's redirects are
also cached in Redis.Workaround:
repair_injiweb_client_redirect_uriin deploy.sh
appends the current redirect to the DB list andDELs the Redis
clientdetails::wallet-demo-clientcache. Idempotent. -
SD-JWT credentials don't get a QR on PDF export. Mimoto's pixelpass
library is designed for structured JSON-LD VCs (CBOR-serialize
credentialSubject → zlib → base45); SD-JWT is already a compact JWS
string so the pipeline doesn't apply. v0.16.0 ships no alternative
SD-JWT QR path. Not fixed — pick LDP Farmer (V2 or plain) if you
need a QR; SD-JWT credential is storage-only. -
Auth-Code + Mimoto rejects Farmer Credential and Farmer Credential (V2)
witherr_signature_verification_failed. The/v1/mimoto/credentials/download
call returns HTTP 400 "we were unable to download the card" after a
successful eSignet login. SD-JWT variant works; LDP_VC variants don't.The bug is in MOSIP's vc-verifier library, not in Inji Certify's
signing. We proved this end-to-end:- Intercepted the VC Inji Certify hands Mimoto via tcpdump on Mimoto's
netns (port 80 on certify-nginx upstream). - Ran the intercepted VC through pyld (reference Python URDNA2015) +
pynacl Ed25519 verify, using the same public key certify-nginx's
did.json advertises. Result: VALID. Signature matches
SHA256(canon(proofOpts)) || SHA256(canon(doc)) per the
Ed25519Signature2020 / W3C Data Integrity spec. - Posted the same VC to Inji Verify's
/v1/verify/vc-verification
endpoint (which also usesio.mosip.vercred.vcverifier). Result:
INVALID — same library, same rejection, independently of Mimoto.
Conclusion: the library's URDNA2015 canonicaliser disagrees with the
reference spec implementation for this VC. Most likely divergence points:
theBitstringStatusListEntrycredentialStatus block (VCDM 2.0 feature)
or the{"@vocab": "…"}context fragment — setting
mosip.certify.issuer.ledger-enabled=falsein the Farmer plugin config
doesn't actually stripcredentialStatus, and replacing@vocabwith
explicit term definitions didn't fix it either. Both tested here.The danubetech/ld-signatures-java version Mimoto ships (v0.16.0) is
older than Inji Certify's (v0.14.0). MOSIP's tested matrix is Mimoto
v0.16.0 ↔ Inji Certify v0.13.1 — we run v0.14.0. Upstream issue to
track against mosip/vc-verifier, not a verifiably-go fix.Workaround: use Farmer Credential (SD-JWT) in Auth-Code
demos. SD-JWT verification is a plain JWS signature check — no
URDNA2015, no context expansion, no canonicalisation — and
round-trips cleanly. The LDP variants are "issue-only" for Auth-Code- Inji Web until Mimoto ships with an updated vc-verifier library.
Reproduction (for tracking progress against upstream):
# 1. capture a VC from Mimoto's download flow docker run -d --rm --name mimoto-tcpdump \ --network=container:injiweb-mimoto \ --cap-add=NET_ADMIN --cap-add=NET_RAW \ -v /tmp/pcap:/cap nicolaka/netshoot \ tcpdump -i any -A -s 0 -w /cap/mimoto.pcap 'tcp port 80' # drive the failing Auth-Code + Farmer Credential (V2) flow in the UI docker stop mimoto-tcpdump grep -a -o '{"credential":.\{500,6000\}"proof":[^}]*}}*' /tmp/pcap/mimoto.pcap | head -1 > /tmp/vc.json # 2. verify via pyld + pynacl (reference implementations) python3 -m venv /tmp/vv && /tmp/vv/bin/pip install pyld pynacl base58 requests /tmp/vv/bin/python - <<'PY' # (see docs/dpg-matrix.md — same script runs pyld URDNA2015 + pynacl Ed25519) PY # → VALID # 3. verify via MOSIP's library docker run --rm --network waltid_default -v /tmp/vc.json:/b.json:ro \ curlimages/curl:latest -s -X POST -H 'Content-Type: application/json' \ -d @/b.json http://inji-verify-service:8080/v1/verify/vc-verification # → {"verificationStatus":"INVALID"} - Intercepted the VC Inji Certify hands Mimoto via tcpdump on Mimoto's
Inji Verify v0.16.0
What works
- Direct upload / paste of JSON-LD VCs →
POST /v1/verify/vc-verification - SD-JWT VC submission (v0.16.0 added
POST /vc-submission+
GET /vp-result/{transactionId}) - OID4VP cross-device flow via the Inji Verify SPA (full flow)
Known bugs we work around
-
Missing
/assets/config.jsoncrashes the result screen. The UI
fetches this file at boot for its per-credential field render-order
map. Upstream v0.16.0 ships without it, so nginx 404s fall through to
index.html, the UIJSON.parses HTML, gets an empty object, then
crashes withCannot read properties of undefined (reading 'map')
after every successful verification.Workaround: we mount
deploy/injiweb-overrides/inji-verify-config.jsoninto the
inji-verify-ui container at/usr/share/nginx/html/assets/config.json
with render orders for the Farmer credential (and stubs for the
other types the UI's switch covers). -
INJIVER-1131 (cross-device): Inji Verify v0.16.0 can report
SUCCESS for a VC whose claims don't match the requested fields in a
presentation definition. Ourinjiverifyadapter re-checks the
disclosed claims against the requested fields and downgrades the
verdict if they don't match. This is flagged asCaveatson the
Inji Verify DPG card. -
Tested-compatibility matrix: per MOSIP's own release notes, Inji
Verify v0.16.0 was tested against Inji Certify v0.13.1 and Inji
Web v0.17.0. We run v0.14.0 + v0.16.0 — so the two workarounds
above (did.json kids + assets/config.json) also paper over pairing
mismatches. Upstream is moving to a cleaner verify-service +
canonicalization pipeline in their next minor.
Cross-stack compatibility summary
| Issuer ↓ / Holder → / Verifier → | walt.id wallet | Inji Web Wallet | walt.id verifier | Inji Verify |
|---|---|---|---|---|
| walt.id issuer | End-to-end | Not supported (Inji Web is catalog-initiated, not offer-consuming) | End-to-end | Works for W3C VCDM formats after @context alignment |
| Inji Certify pre-auth | End-to-end | Not compatible (Mimoto assumes auth-code) | Works — adapter re-canonicalizes | Works (with inji-proxy kid fix) |
| Inji Certify auth-code | Not supported (walt.id wallet has no eSignet login) | End-to-end | Works | Works (with inji-proxy kid fix) |
The DPG selection cards in the UI reflect these combinations via their
Capabilities arrays — users only see combinations that have been verified
to work.