OpenID4VP DCQL
A Dart library for building and validating Digital Credentials Query Language (DCQL) queries as defined in the OpenID for Verifiable Presentations (OpenID4VP) v1.0 specification.
Build complex credential queries with a fluent, type-safe API, validate them against the spec, and serialize them to JSON for transmission.
Package version to Spec
List of package versions and what specs they support
| version | Spec |
|---|---|
| v1.0.0 | v1.0 |
| v1.0.1 | v1.0 |
Why
- Fluent Builder API: Construct complex nested queries with readable, chainable methods.
- Type Safety: Compile-time checks for known credential types (
mdoc,sd-jwt) and claims. - Spec Compliance: Built-in validation ensures your queries meet the DCQL specification requirements.
- Zero Boilerplate: No need to manually construct deeply nested Maps or JSON objects.
What
This library focuses exclusively on the Digital Credentials Query Language (DCQL) part of the OpenID4VP specification.
It does not handle
- Cryptographic operations (signing, encryption, or verification of credentials).
- PKI or Key Management.
- Transport protocols (OID4VP request/response handling).
It is designed to be used within a larger OpenID4VP implementation or by a Verifier application that needs to construct queries.
Install
dart pub add openid4vp_dcql
Core Example
import 'dart:convert';
import 'package:openid4vp_dcql/openid4vp_dcql.dart';
void main() {
try {
final query = DcqlBuilder()
// Request an mDoc Driving License
.credential('credential-1', type: CredentialType.mdocDl)
.claim(Claims.mdocDl.firstName, id: 'first_name')
.claim(Claims.mdocDl.documentNumber, id: 'doc_number')
// Define combinations of claims that satisfy the requirement
.claimSet(["first_name", "doc_number"])
// Request an SD-JWT PID
.credential('credential-2', type: CredentialType.sdJwtPid)
.claim(Claims.sdJwtPid.documentNumber)
// Define logic between credentials (e.g., Credential 1 OR Credential 2)
.credentialSet()
.option(['credential-1'])
.option(['credential-2'])
// Build will throw a ValidationException if the query is invalid
// can be skipped by setting (skipValidation: true)
.build();
print(jsonEncode(query.toJson()));
} catch (e) {
print(e);
}
}
Manual Construction
You can also construct the query object directly without using the builder. However, you will lose some conveniences, such as automatic path prefixing (namespaces) for claims.
import 'dart:convert';
import 'package:openid4vp_dcql/openid4vp_dcql.dart';
void main() {
final query = DcqlQuery(
credentials: [
Credential(
id: 'credential-1',
format: Formats.mso_mdoc,
meta: Meta(meta: {'doctype_value': 'org.iso.18013.5.1.mDL'}),
claims: [
Claim(id: 'first_name', path: ['org.iso.18013.5.1', 'first_name']),
Claim(id: 'doc_number', path: ['org.iso.18013.5.1', 'document_number']),
],
claimSets: [
['first_name', 'doc_number']
],
),
Credential(
id: 'credential-2',
format: Formats.sd_jwt,
meta: Meta(meta: {'vcts_values': ['urn:eu.europa.ec.eudi.pid.1']}),
claims: [
Claim(path: ['document_number']),
],
),
],
credentialSets: [
CredentialSet(
options: [
['credential-1'],
['credential-2'],
],
),
],
);
// Validate the query structure
final validation = DcqlValidator().validate(query);
if (validation.isValid) {
print(jsonEncode(query.toJson()));
} else {
print('Invalid query: ${validation.errors}');
}
}
Features
Fluent Builder
The DcqlBuilder allows you to chain methods to define credentials, claims, and sets naturally.
Validation
The library includes a robust validator DcqlValidator that checks for:
- Uniqueness: Ensures all credential and claim IDs are unique within their scope.
- Referential Integrity: Verifies that all IDs referenced in
claim_setsandcredential_setsactually exist. - Structure: Checks for non-empty paths, correct value types, and required fields.
- Format Compliance: Validates format-specific requirements (e.g.,
doctype_valuefor mdoc).
You can validate a query object or a JSON string:
final validator = DcqlValidator();
// Validate a DcqlQuery object
final result = validator.validate(query);
// Validate a JSON string
final resultJson = validator.validateJson(jsonString);
if (result.isInvalid) {
print('Validation failed:');
for (final error in result.errors!) {
print('- $error');
}
}
Note: The
DcqlBuilder.build()method automatically runs validation and throws aValidationExceptionif the query is invalid. To skip this check, use.build(skipValidation: true).
Supported Formats
mso_mdoc(Mobile Driving License, etc.)dc+sd-jwt(SD-JWT VC)
Contributing
Open an issue for discussion, then PR with tests.
License
MIT
Libraries
- builder/credential_builder
- builder/credential_set_builder
- builder/dcql_builder
- claim
- claim_set
- constants
- credential
- credential_set
- dcql_query
- enum/credential_type
- enum/doc_type
- enum/format
- extensions/meta_set_filter_extension
- impl/claims
- impl/credential_types
- impl/default_validation
- impl/doc_types
- impl/formats
- json
- meta
- openid4vp_dcql
- OpenID for Verifiable Presentation (DCQL) Builder library.
- validation/dcql_validator