Repository navigation
DCQL credential query parser with claims/values matching #4087
Description
Parent PRD
#4067 (see PRD comment)
What to build
Standalone DCQL credential query parser that evaluates DCQL credential queries (OpenID4VP sections 6.1/6.3/7) against a list of Verifiable Credentials and returns matching VCs.
Interface: takes a DCQL credential query object and a list of VCs, returns the subset that matches (or an error for invalid queries).
Spec compliance
This implements a subset of the DCQL specification (OpenID4VP 1.0 sections 6 and 7). The supported and unsupported features are documented in the package.
Credential Query (section 6.1) — supported fields:
id(REQUIRED): validated per spec (non-empty, alphanumeric/underscore/hyphen only)claims(OPTIONAL): array of claims queries
Credential Query — not supported (not needed for our use case):
format: credential format selection is handled by PD matchingmeta: credential metadata constraints are handled by PD matchingmultiple: we usematch_policyin the filter chain insteadclaim_sets: not needed for our value-matching use casetrusted_authorities: trust is handled by PD matching and DID resolutionrequire_cryptographic_holder_binding: handled by VP verification
Claims Query (section 6.3) — supported fields:
path(REQUIRED): Claims Path Pointer per section 7 (strings, integers, null)values(OPTIONAL): exact value matching with OR semantics
Claims Query — not supported:
id: only needed whenclaim_setsis usedclaim_setson the credential query: not needed
Claims Path Pointer (section 7) — supported:
- String elements: key lookup in JSON objects
- Non-negative integer elements: array index lookup
- Null elements: wildcard, selects all elements of an array
- Path starts at the credential root (not scoped to
credentialSubject)
Implementation details
- Exact value matching via
valuesparameter (strings, integers, booleans) - OR semantics when multiple
valuesare specified (match if any value matches) - Multiple
claimsentries in a single query (AND semantics — all must match) - Path resolution supports the full credential JSON (root-level fields like
type,issuer, as well as nestedcredentialSubjectfields) credentialSubjectis unwrapped from its Go array representation to a single object for ergonomic path access
No integration with PD matching, wallet, or API yet — this is purely the matching engine.
See "DCQL Support" and "DCQL credential query parser" in the PRD for full context.
Acceptance criteria
- Parses DCQL credential query objects with
idandclaimsarray - Validates
idper spec: non-empty, alphanumeric/underscore/hyphen characters only - Returns error for invalid credential query (empty or invalid
id) - Path resolution starts at the credential root, supporting top-level fields (
type,issuer, etc.) - Path supports string elements (key lookup in objects)
- Path supports non-negative integer elements (array index lookup)
- Path supports null elements (wildcard: select all array elements)
- Matches
valueswith exact equality for strings, integers, and booleans - Multiple
valuesin a single claim query use OR semantics - Multiple
claimsentries use AND semantics - Returns all matching VCs from the input list
- Returns empty list (not error) when no VCs match
- Handles edge cases: missing fields in credential, empty
claimsarray, deeply nested paths - Supported DCQL subset is documented in the package
- Unit tests covering all of the above
- Benchmark: ~14ms worst case for 2000 credentials
Blocked by
None.
User stories addressed
- User story 7: standard DCQL syntax
- User story 10: exact value matching on claim fields
- User story 11: multiple values with OR semantics
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Activity
#4087: DCQL parser — tracer bullet: single claim value matching
#4087: DCQL parser — test non-matching value returns empty
#4087: DCQL parser — test nested path resolution
#4087: DCQL parser — test multiple values OR semantics
#4087: DCQL parser — test multiple claims AND semantics
#4087: DCQL parser — test missing field and empty credentialSubject
#4087: DCQL parser — test empty list and multiple credentials filtering
#4087: DCQL parser — test integer and boolean value matching
#4087: DCQL parser — test claim without values (existence check)
#4087: DCQL parser — test JSON-deserialized query and credential
#4087: DCQL parser — add ID validation and error return
#4087: DCQL parser — root-level path resolution
#4087: DCQL parser — array index path support, Path type []any
#4087: DCQL parser — null wildcard path support
#4087: DCQL parser — add benchmark for 2000 credentials
#4087: DCQL parser — add README documenting supported subset
#4087: Address PR review feedback
#4087: Address PR feedback — validate paths and credentialSubject arrays
#4087: Document credentialSubject array handling in README
#4087: Handle credentialSubject as both object and array
#4087: Fix non-zero index on single credentialSubject, add coverage t…
reinkrul commentedon Mar 25, 2026
Alternative approach:
Don't know if that order always works in all cases, but it does for the DelegationCredential. Because if you know which care organization it's about, you then know which DelegationCredential you need for the
client attestation.
(so through parameterization of the PD, essentially the same as with this proposal:
"credential_selection": { "patient_id": "123456789" }
the principle would also work with DCQL by the way)"
stevenvegt commentedon Mar 25, 2026
Yes, the credential_selection route is simpler for the use and doesn't require a DCQL parser. Too bad, I liked this implementation. But we can close this one.