OpenID for Verifiable Presentations (OpenID4VP)
The IDK already implements the full OpenID4VP verifier, the holder/wallet side, the DCQL query language, the Universal OID4VP API for backend integration, and a default in-memory DCQL store. The protocol details, request/response flows, JAR signing, JARM encryption, and the supported credential formats are documented in the IDK OpenID4VP guide; the EDK does not reshape any of that.
What the EDK adds is the production storage, transport, and lifecycle layer around it: a relational, version-history-preserving DCQL store with its own admin and history REST endpoints; a semantic-to-DCQL authoring path so non-developers can compose queries from attribute catalogs; a verifier-DCQL binding store (VDX) that lets multiple verifiers share a single tenant-scoped DCQL query at different pinned versions; scheduled future version activations driven by the EDK scheduler; routed-command transport for distributed deployments; and tenant-path-aware public verifier endpoints. This section covers those additions; protocol-level material stays in the IDK guide.
What the EDK Adds
Versioned DCQL store. The IDK contract is DcqlQueryConfigurationStore, a key-value-ish CRUD interface with no concept of history. The EDK replaces it with VersionedDcqlQueryConfigurationStore, which honors the same contract but appends an immutable version row to a shared config_version table on every write and advances a current-version pointer in a typed dcql_query header table. Reads return the body that the current-version pointer references. The EDK adds listVersions, getVersion, and restoreVersion operations on top, and exposes them as REST endpoints at /api/v1/oid4vp/dcql/{queryId}/versions[/{version}[/restore]]. See DCQL Store.
Semantic-to-DCQL authoring. Building a DCQL query by hand requires knowing the credential-type binding registry, the claim path conventions, and DCQL's credential_sets semantics. The EDK ships SemanticToDcqlConverter, a mechanical translator from semantic attribute selections (AttributeSelection(attributeSetId, selectedPaths)) to a fully-formed DcqlQuery, with optional intent_to_retain stamping and optional credential_sets wrapping. Both the lightweight authoring path and the enterprise authoring UI produce the same SemanticToDcqlConversionRequest and call the same converter. See DCQL Authoring.
Verifier-DCQL bindings (VDX). A tenant typically owns one DCQL query for a use case (age_verification, identity_check) but hosts multiple verifiers that each want to use that query at a specific pinned version. The VDX VerifierDcqlBinding is the (verifierId, dcqlQueryId, pinnedVersion) triple that captures that pin, with enabled and alias metadata. Two verifiers can bind the same query at different versions; rolling one verifier forward to a new DCQL version does not affect the others. Bindings have their own REST surface under /api/services/v1/oid4vp/verifiers/{verifierId}/dcql and a reverse-lookup endpoint at /api/v1/oid4vp/dcql/{queryId}/verifiers. See Verifier Bindings.
Scheduled activations. A verifier binding can also have a scheduled future activation: "at effectiveAt, repoint this binding from version 5 to version 7". The activation is a row in the EDK scheduler's scheduled_command table; the binding system projects pending activations as VerifierDcqlScheduledActivation records and lets operators list and cancel them. This is how regulated workflows move every verifier in a tenant to a new DCQL version on a known cutover date. Covered in Verifier Bindings.
Tenant-aware verifier paths. The public verifier endpoints (request_uri, direct_post) carry no bearer token, so the IDK resolves the tenant from the host header. The EDK adds the option of a leading path slug (/{tenantSlug}/oid4vp/request-uri/...) through TenantAwareOid4vpVerifierHttpAdapter, which tries an as-is match first and only falls back to slug lookup when no host match wins. Host-only deployments are unaffected.
Routed-command transport. Every IDK verifier, holder, universal, and common OID4VP command is wrapped in a generated *Routed class through the per-package RoutedCommandsSpec manifests (Oid4vpVerifierRoutedCommandsSpec, Oid4vpHolderRoutedCommandsSpec, UniversalOid4vpRoutedCommandsSpec, Oid4vpCommonRoutedCommandsSpec). A wallet, a verifier UI, or a backend integration can hold the IDK service interface and stay unaware that calls travel over HTTP RPC to a remote service. See the Command Transport guide.
Auth bridge. Wallet presentations can be translated into OAuth2/OIDC sessions through the EDK auth bridge, so a downstream service that expects a Bearer token can be fed by a wallet flow without speaking OpenID4VP itself.
How the Pieces Fit Together
In a typical EDK deployment the verifier service exposes both the OpenID4VP public endpoints (/oid4vp/request-uri/..., /oid4vp/direct_post, optional /oid4vp/backend/auth/requests Universal API) and the DCQL admin surface (/api/v1/oid4vp/dcql/..., /api/services/v1/oid4vp/verifiers/{verifierId}/dcql/...). The admin endpoints write to the versioned DCQL store, which is backed by PostgreSQL or MySQL; the public endpoints resolve DCQL queries through the version-aware DcqlQueryResolver, which checks the verifier binding (if a verifierId is in scope), pulls the pinned version's body, and feeds it into the IDK authorization-request creator.
Where Things Live
| Concern | Module |
|---|---|
| Versioned DCQL store contract + impl | com.sphereon.edk:lib-oid4vp-dcql-store-versioned-public / -impl |
| PostgreSQL DCQL persistence | com.sphereon.edk:lib-oid4vp-dcql-store-versioned-persistence-postgresql |
| MySQL DCQL persistence | com.sphereon.edk:lib-oid4vp-dcql-store-versioned-persistence-mysql |
| DCQL version REST adapter | com.sphereon.edk:lib-oid4vp-dcql-store-versioned-rest |
| Semantic-to-DCQL authoring | com.sphereon.edk:lib-oid4vp-dcql-authoring-public / -impl |
| Verifier-DCQL binding store (VDX) | com.sphereon.vdx:lib-data-store-oid4vp-dcql-binding-public / -service-impl |
| Verifier binding REST adapters | com.sphereon.vdx:lib-data-store-oid4vp-dcql-binding-rest |
| Verifier binding persistence | ...-persistence-postgres / -persistence-mysql |
| Verifier-aware DCQL resolver | com.sphereon.vdx:lib-data-store-oid4vp-dcql-binding-resolver |
| Tenant-path-aware verifier endpoints | com.sphereon.edk:lib-oid4vp-verifier-rest-tenant |
| Routed-command manifests | com.sphereon.edk:lib-oid4vp-{verifier,holder,universal,common}-remote |
| Auth bridge (OID4VP to OAuth2/OIDC) | com.sphereon.edk:lib-oid4vp-auth-bridge-api / -impl |
Next Steps
- Integration: the Universal OID4VP API guide (works against either IDK or EDK verifier stacks)
- DCQL Store: the storage model, the versioning semantics, and how resolution snapshots queries into authorization sessions
- DCQL REST API: every admin and version-history endpoint, with request/response shapes
- DCQL Authoring: the semantic-to-DCQL converter
- Verifier Bindings: per-verifier DCQL pinning, scheduled activations, REST surface
- Interactive API Docs: full OpenAPI for the Universal OID4VP API