Digital Credentials
The IDK credential design guide explains the underlying model: credential designs that bind claim presentations, render variants, displays, and assets to a credential type; issuer and verifier designs for branding; and a layered resolution engine that combines metadata from OID4VCI, SD-JWT VCT, JSON Schema, OCA, and local overrides. That model is what your code reads from when it needs to render a credential or build issuer metadata. The EDK does not change that model. It takes the in-memory IDK service and makes it operable as a multi-tenant production service.
If you have never used the IDK design service before, read the IDK guide first. This section assumes you understand CredentialDesignRecord, DesignBinding, ClaimPresentation, RenderVariant, and ResolvedCredentialDesign. The EDK pages tell you what additional capabilities you get on top.
Who Reads What
Pick the page that matches what you are trying to do:
"I'm building a service that issues or verifies credentials." You will use the CredentialDesignService interface exactly as documented in the IDK guide. In the EDK it is backed by PostgreSQL or MySQL instead of an in-memory store. There is nothing new to learn at the API level. Wire one of the persistence modules listed in Persistence and the rest of your code stays the same. The OID4VCI issuer in the EDK reads designs to build its .well-known/openid-credential-issuer metadata and to decide selective-disclosure policy per claim at issuance time; that path is fully wired and needs only the design content.
"I need to manage designs from outside the application: from CI, from an admin UI, from a CLI." Use the REST API. It is a faithful HTTP projection of the IDK service interface, mounted at /api/v1/designs/.... Authentication, tenant resolution, and authorization come from the standard EDK layers.
"I want to mark approved snapshots of a design for audit or rollback purposes." Use Versioning. It is an explicit snapshot mechanism, not an auto-on-every-write change log. Call createDesignVersion when you want to commit a checkpoint; the EDK does not snapshot for you on regular create/update.
"I'm building a wallet or verifier UI that needs to keep rendering credentials when the network is down." Use the caching wrapper. It is a failover cache: reads go to the remote first and fall back to the local copy if the remote is unreachable, so the cache only matters when something has gone wrong.
"I want OCA bundles to drive my credential metadata." Use the OCA section. OCA bundles can be imported as persistent designs or passed inline at resolution time without being stored.
What the EDK Adds
Concretely, what you get on top of the IDK base:
SQL-backed persistence. The IDK ships a blob-store-backed DefaultCredentialDesignService that is fine for tests and single-process tools. The EDK ships DefaultVersionedCredentialDesignService which is wired to PostgreSQL or MySQL repositories generated by SQLDelight. The repository surface is the same; the EDK binding replaces the IDK default via Metro replaces, so dropping the EDK persistence module on the classpath is the only required change for a service to move from in-memory to SQL.
A REST adapter. The CredentialDesignHttpAdapter (VDX module lib-data-store-credential-design-rest-vdx) exposes the entire CredentialDesignService surface as HTTP endpoints under /api/v1/designs/.... Designs are managed from outside the JVM without writing controllers. The adapter is mounted automatically when the module is on the classpath of a host application that has the Universal HTTP Adapter wired.
Explicit version snapshots. VersionedCredentialDesignService (the EDK service interface that extends CredentialDesignService) adds four operations: createDesignVersion snapshots the current live state of one design into an immutable config_version row, listDesignVersions returns the history, getDesignVersionContent reads any historical snapshot, and setLatestDesignVersion updates the "this version is the blessed one" pointer. These are operator/audit operations; ordinary reads through getCredentialDesign continue to return the live row, not a historical snapshot.
Offline failover cache. CachingCredentialDesignService wraps a remote CredentialDesignService and a local BlobService. Reads go to the remote first and fall back to the local cache only when the remote call fails. Writes go through to the remote and update the cache on success. This is the right primitive for wallets and verifier UIs that need to keep rendering credentials during a network outage; it is not a performance cache for healthy traffic.
OCA bundles as a metadata source. OCA bundles can be parsed, processed, and SAID-verified through OcaBundleService. They feed credential design via OcaBundleDesignProvider (one layer in the IDK resolution pipeline) and OcaDesignMapper (the import path that produces a persistent design from a bundle). The original bundle is preserved natively for round-tripping.
End-to-End: an OID4VCI Issuer
To make this concrete, here is how a real EDK consumer uses the design service. The OID4VCI issuer in the EDK builds credential_configurations_supported for its OID4VCI metadata endpoint from credential designs. At startup it calls:
val designs = designService.listCredentialDesigns(tenantId).getOrElse { return emptyMap() }
val result = mutableMapOf<String, CredentialConfigurationSupported>()
for (design in designs) {
val configIdBindings = design.bindings.filter { it.credentialConfigurationId != null }
if (configIdBindings.isEmpty()) continue
val resolved = designService
.resolveCredentialDesign(tenantId, ResolveCredentialDesignInput(designId = design.id))
.getOrElse { continue }
for (binding in configIdBindings) {
val configId = binding.credentialConfigurationId!!
val format = resolveFormat(binding)
result[configId] = Oid4vciDesignMapper.toCredentialConfiguration(resolved, format)
}
}
(From DesignBackedOid4vciIssuerConfigProvider.buildCredentialConfigurationsAsync.)
The issuer is treating the design store as the source of truth for what credential types it offers. Adding a new credential configuration means creating a new credential design with a credentialConfigurationId binding. There is no separate "issuer config" file to keep in sync.
Later, when the issuer actually issues a credential, it looks up the same design to decide which claims are mandatory and which are selectively disclosable (DeferredPipelineReExecutor.resolveDesignContext). The ClaimPresentation.mandatory and ClaimPresentation.sdPolicy fields are read straight from the resolved design and translated into the OID4VCI runtime policy. So the same edit that updates the metadata also updates issuance behaviour.
This is the pattern: the design is the policy, not just the display metadata. Putting your designs in SQL through the EDK persistence layer means the issuer's configuration is in SQL, edited through the design REST API, optionally snapshotted through versioning, and audited like any other data.
Where the Modules Live
| Concern | Module |
|---|---|
| Service interface (IDK) | com.sphereon.idk:lib-data-store-credential-design-public |
| In-memory default impl (IDK) | com.sphereon.idk:lib-data-store-credential-design-impl |
| Versioned service interface (EDK) | com.sphereon.edk:lib-data-store-credential-design-persistence-api |
| Versioned service impl, OCA mappers (EDK) | com.sphereon.edk:lib-data-store-credential-design-impl |
| PostgreSQL repositories | com.sphereon.edk:lib-data-store-credential-design-persistence-postgresql |
| MySQL repositories | com.sphereon.edk:lib-data-store-credential-design-persistence-mysql |
| Offline caching wrapper + sync | com.sphereon.edk:lib-data-store-credential-design-cache |
| Routed-command transport (client) | com.sphereon.edk:lib-data-store-credential-design-remote |
| HTTP REST adapter (server) | com.sphereon.vdx:lib-data-store-credential-design-rest-vdx |
| OCA primitives | com.sphereon.edk:lib-data-oca-public / -impl |
Next Steps
- Design Overview: the EDK service surface on top of the IDK
CredentialDesignService - REST API: how to drive the design service from outside the JVM
- Versioning: how the explicit snapshot operations work and how rollback is done
- Persistence: PostgreSQL and MySQL backends, and the offline failover cache
- OCA Bundles: OCA as a credential design source