From 9dc9315b476e63b9b1705c6523afd73b4ac99426 Mon Sep 17 00:00:00 2001
From: Patrick St-Louis Query By Example
such as bbs-2023 or ecdsa-sd-2023 in the acceptedCryptosuites array.
+The following algorithm specifies how a conforming [=holder=] implementation
+determines whether a [=verifiable credential=] matches the selection criteria
+in a QueryByExample credentialQuery object. Required inputs are a
+[=verifiable credential=] ([=map=] credential) and a
+credentialQuery object ([=map=] credentialQuery). A
+boolean match result is produced as output. A conforming implementation MUST
+produce the same output as this algorithm.
+
+Matching proceeds in two stages. First, if an example is present,
+each of its properties is treated as a requirement against
+credential. Second, if acceptedIssuers is present, the
+credential's issuer MUST be acceptable. The credential matches only if both
+stages succeed when present.
+
false.
+ example property,
+initialize example to its value and perform the following steps:
+ @context property, initialize
+expectedContexts to its value normalized to a [=list=], and
+initialize credentialContexts to the value of the
+@context property of credential normalized to a
+[=list=]. If the length of credentialContexts is less than the
+length of expectedContexts, return false. For each
+index i from 0 to the length of
+expectedContexts minus one, if
+expectedContexts[i] is not strictly equal to
+credentialContexts[i], return false.
+ type property, initialize
+expectedTypes to its value normalized to a [=list=], and initialize
+credentialTypes to the value of the type property of
+credential normalized to a [=list=]. If no value in
+expectedTypes is strictly equal to any value in
+credentialTypes, return false.
+ @context and type properties removed, if present. If
+remaining contains any properties, set match to the
+result of running the algorithm in Section
+[[[#matching-object-properties]]], passing remaining as
+expectedObject and credential as
+actualObject. If match is false, return
+false.
+ acceptedIssuers
+property, initialize acceptedIssuers to its value and perform the
+following steps:
+ issuer property of credential. If
+credentialIssuer is a [=map=], initialize
+credentialIssuer to the value of its id property.
+ false. An item is
+acceptable if any of the following is true:
+ id property whose
+value is strictly equal to credentialIssuer.
+ recognizedIn
+property, and credentialIssuer is recognized according to the
+[[[VC-RECOG-ENT]]] specification using that property's value.
+ true.
+
+The reason, acceptedCryptosuites, and
+acceptedEnvelopes properties of a credentialQuery
+object are not used during credential matching. The reason
+property is intended for display to the [=holder=] by their software. The
+acceptedCryptosuites and acceptedEnvelopes properties
+inform the [=holder=]'s software about which proof mechanisms and envelope
+formats the [=verifier=] will accept, and are used during presentation
+construction rather than credential selection.
+
+This algorithm compares JSON structure and values. It does not require JSON-LD +compaction, expansion, or term rewriting. Implementations MAY apply JSON-LD +transformations before matching, provided the boolean result is the same as +this algorithm when run on the transformed inputs. +
+
+The following algorithm determines whether every property of an expected object
+is satisfied by an actual object. It is used recursively for nested objects
+such as credentialSubject. Required inputs are an expected object
+([=map=] expectedObject) and an actual object ([=map=]
+actualObject). A boolean is produced as output.
+
false.
+ ""), continue
+to the next property. An empty string indicates that the property MUST exist,
+but any value is acceptable.
+ true when called with expectedValue as
+expectedObject and the element as actualObject. If no
+such element exists, return false.
+ false, return false.
+ false.
+ "21" and
+the number 21). A value is eligible for coercion only if it is a
+[=string=] that represents a valid numeric value in its entirety; strings that
+contain non-numeric characters MUST NOT be coerced.
+ true.
+ +This recursive property matching algorithm is functionally equivalent to +flattening the expected object into a map of +JSON Pointer paths paired +with expected values, and then checking each path against the credential. +Implementations MAY use either approach, provided the results are equivalent. +See also Section [[[#converting-querybyexample-to-json-pointers]]]. +
+
+The following algorithm converts a QueryByExample example object
+into a list of JSON
+Pointers that specify which fields to reveal for [=selective disclosure=],
+such as the selectivePointers option used with credential
+derivation (see Section [[[#derive-credential]]]). Required input is an
+example object ([=map=] example). An array of JSON Pointer strings
+(pointers) is produced as output. A conforming implementation that
+converts a QueryByExample example for [=selective disclosure=]
+MUST produce the same output as this algorithm.
+
@context property removed, if present.
+ /type and /issuer when those properties are
+required to be disclosed by the securing mechanism in use.
+
+The following example uses the Permanent Resident Card QueryByExample from this
+section. After removing @context, generating pointers, adding
+mandatory VCDM 2.0 reveal pointers, ensuring
+credentialSubject coverage, pruning shallow pointers, and
+normalizing type pointers, a conforming conversion produces:
+
+{
+ "selectivePointers": [
+ "/type",
+ "/issuer",
+ "/credentialSubject/birthCountry"
+ ]
+}
+
+
+
+In this result, /type and /issuer are the explicit
+mandatory reveal pointers for the VC Data Model 2.0 securing mechanism in use,
+and /credentialSubject/birthCountry is the claim requested by the
+example (via an empty-string value). These pointers are suitable for use as
+selectivePointers when deriving a credential for presentation.
+
+The following algorithm adjusts a list of JSON Pointers produced from a
+QueryByExample example so they are suitable for selective
+disclosure. Required input is an array of JSON Pointer strings
+(pointers). An array of JSON Pointer strings is produced as output.
+
/credentialSubject and no pointer has
+/credentialSubject/ as a prefix, append
+/credentialSubject to pointers.
+ /type/ in pointer, or -1 if it does not
+occur.
+ -1, append the substring of
+pointer from the start through /type (that is, truncate
+any array index after /type) to adjustedPointers.
+Otherwise, append pointer to adjustedPointers.
+ +The following algorithm retains only the deepest JSON Pointers from a list, so +that a shallow pointer is removed when a deeper pointer under the same path +exists. Required input is an array of JSON Pointer strings +(pointers). An array of JSON Pointer strings is produced as output. +
+ +
+For example, given
+["/a/b", "/a/b/c", "/a/b/c/d"], the result is
+["/a/b/c/d"].
+
true.
+ false and stop comparing for this
+pointer.
+ true, append pointer to
+deep.
+ false.
+At least one element expectedElement in expectedValue
+MUST match at least one element actualElement in
+actualValues. An expectedElement matches an
+actualElement if any of the following is true:
+ true when called with
+expectedElement as expectedObject and
+actualElement as actualObject.
+ false.
/type and /issuer when those properties are
-required to be disclosed by the securing mechanism in use.
+Append /type and /issuer to pointers if
+they are not already present. These pointers are the deterministic mandatory
+reveal paths for selective disclosure conversion under
+[[VC-DATA-MODEL-2.0]]. Securing mechanisms MAY require additional mandatory
+pointers at issuance time; those are outside the scope of this conversion.
The following example uses the Permanent Resident Card QueryByExample from this
-section. After removing @context, generating pointers, adding
-mandatory VCDM 2.0 reveal pointers, ensuring
-credentialSubject coverage, pruning shallow pointers, and
-normalizing type pointers, a conforming conversion produces:
+section. After removing @context, generating leaf pointers
+(including /credentialSubject/birthCountry from the empty-string
+claim), appending the mandatory /type and /issuer
+pointers, ensuring credentialSubject coverage, pruning shallow
+pointers, and normalizing type pointers, a conforming conversion
+produces:
@@ -2020,9 +2045,9 @@Converting QueryByExample to
-In this result, /type and /issuer are the explicit
-mandatory reveal pointers for the VC Data Model 2.0 securing mechanism in use,
-and /credentialSubject/birthCountry is the claim requested by the
+In this result, /type and /issuer are always added by
+the conversion algorithm as mandatory reveal pointers, and
+/credentialSubject/birthCountry is the claim requested by the
example (via an empty-string value). These pointers are suitable for use as
selectivePointers when deriving a credential for presentation.
+An informative reference algorithm for walking [=exchange=] steps until client +input is required or a response is ready is provided in Appendix +[[[#reference-workflow-step-processing-algorithm]]]. +
+A given interaction with an exchange is expected to be short-lived but other mechanisms can be used to enable longer or multi-stage interactions. Examples of other interaction mechanisms include SMS, email, web notifications, @@ -4895,6 +4900,267 @@
+This appendix is non-normative. +
+ +
+This specification does not mandate a single internal implementation for
+advancing an [=exchange=]. The algorithm below documents one possible
+approach for walking [=workflow=] steps until the [=workflow service=] must
+return a partial response to the exchange client (for example, to
+ask for a [=verifiable presentation=]), until the exchange completes, or until
+the exchange fails or times out. Implementations MAY differ in ordering,
+persistence, error handling, and protocol bindings.
+
+Hooks such as prepareStep,
+validateReceivedPresentation,
+validateReceivedPresentationRequest, inputRequired,
+createVerifiablePresentationRequest, and
+isStepComplete exist so that the same logical loop can be adapted
+when exchanges are fronted by this HTTP API, OpenID for Verifiable Presentations
+(OID4VP), OpenID for Verifiable Credential Issuance (OID4VCI), invite-based
+flows, or other interaction mechanisms. The response object
+produced when the loop pauses or finishes can be returned directly to clients
+using this API or mapped into other protocol messages as needed.
+
+The following algorithm processes an exchange by repeatedly evaluating the +current workflow step. Required inputs are a workflow configuration ([=map=] +workflow) and an exchange ([=map=] exchange). Optional +inputs are a received [=verifiable presentation=] ([=map=] +receivedPresentation) and a received [=verifiable presentation +request=] ([=map=] receivedPresentationRequest). A response object +([=map=] response), which MAY be empty, is produced as output, or an +error is raised. +
+ +null.
+ state is complete or
+invalid, throw a NotAllowedError.
+ state is pending, set it to
+active.
+ lastError. Return out of the loop when a
+full response is generated, input from the exchange client is required, or the
+exchange times out. An implementation-specific maximum step count MAY be
+enforced to handle misconfigured workflows. In each iteration:
+ prepareStep hook, passing workflow,
+exchange, step, receivedPresentation, and
+receivedPresentationRequest, to perform any protocol-specific step
+preparation. If prepareStep returns a result with
+receivedPresentation and/or
+receivedPresentationRequest set, update
+receivedPresentation and/or receivedPresentationRequest
+accordingly.
+ validateReceivedPresentation, passing workflow,
+exchange, step, and receivedPresentation.
+ validateReceivedPresentationRequest, passing exchange,
+step, and receivedPresentationRequest.
+ exchange.variables.results[exchange.step].callbackResults, or throw
+any error received.
+ inputRequired hook, passing step and
+receivedPresentation, to perform any protocol-specific input checks.
+ true:
+ null, set it to an empty object.
+ verifiablePresentationRequest is set, call
+createVerifiablePresentationRequest, passing workflow,
+exchange, step, and response.
+ true if
+step.issueRequests includes any issuer requests for
+[=verifiable credentials=] that are to be sent to the client
+(issueRequest.result is not set); otherwise set it to
+false.
+ verifiablePresentation is set or
+issueToClient is true:
+ null:
+ verifiablePresentationRequest is not set,
+set it to an empty object (to indicate that the exchange is not yet complete).
+ verifiablePresentation is set, set
+response.verifiablePresentation to a copy of it;
+otherwise set response.verifiablePresentation to a new,
+empty [=verifiable presentation=] (using [[VC-DATA-MODEL-2.0]] by default; a
+custom configuration MAY specify another version).
+ result is set to an exchange variable
+path or name, save the issued credential in the referenced exchange variable.
+ result is not specified, save the
+issued credential in
+response.verifiablePresentation (for a VCDM
+presentation, append it to
+response.verifiablePresentation.verifiableCredential).
+ verifiablePresentation is set and the step
+configuration indicates it should be signed, sign the presentation (for example,
+by using a VCALM holder instance's /presentations create endpoint).
+ isStepComplete, passing workflow,
+exchange, step, receivedPresentation, and
+receivedPresentationRequest, to perform any protocol-specific
+behavior to determine if the step is complete. Set stepComplete to
+the result, defaulting to true.
+ true:
+ redirectUrl is set:
+ null, set it to an empty object.
+ redirectUrl to
+step.redirectUrl.
+ nextStep is not set, set
+exchange.state to complete.
+ exchange.variables.results[step.nextStep] if it exists, and set
+exchange.step to
+step.nextStep.
+ state is complete, return
+response if it is not null; otherwise return an empty
+object.
+ null and continue the loop.
+ +The following hooks are intentionally underspecified so that implementations can +bind the reference loop to a particular protocol or deployment: +
+ +prepareStep — optional protocol-specific preparation before
+validating client input for the current step.
+ validateReceivedPresentation /
+validateReceivedPresentationRequest — validate a client-supplied
+presentation or presentation request against the current step.
+ inputRequired — determine whether the loop must pause and return a
+response (typically including a presentation request) to the client.
+ createVerifiablePresentationRequest — populate
+response.verifiablePresentationRequest from the step configuration
+and exchange variables.
+ isStepComplete — determine whether the current step is finished and
+the exchange may advance to nextStep or complete.
+