Skip to content

Add support for age_over_nn claims matching - #800

Open
c2bo wants to merge 4 commits into
mainfrom
718-age-over-nn
Open

c2bo wants to merge 4 commits into
mainfrom
718-age-over-nn

Conversation

@c2bo

@c2bo c2bo commented Sep 23, 2026

Copy link
Copy Markdown
Member

Closes #718

Should this be added to 1.0 errata?

Comment thread 1.1/openid-4-verifiable-presentations-1_1.md Outdated
Comment thread 1.1/openid-4-verifiable-presentations-1_1.md Outdated
@brentzundel

Copy link
Copy Markdown
Collaborator

Discussed in group: @c2bo will attempt to rephrase.

Co-authored-by: Christian Bormann <chris.bormann@gmx.de>

Document types can define special rules under which a data element other than the one requested can be returned. In particular, [@ISO.18013-5] defines that when an mDL does not contain a requested `age_over_NN` data element, a different `age_over_NN` data element can be returned by the Wallet - see Section 7.2.5 of [@ISO.18013-5] for the definition on how the `age_over_NN` matching works.

When processing a claims path pointer for an mdoc where its second component refers to a data element that does not exist in the mdoc, the Wallet SHOULD apply any such rule defined for the document type and namespace of the mdoc.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason this isn't a MUST?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have other features like value matching where it is up to the wallet to decide how to deal with that special logic (a SHOULD, not a MUST). It felt in-line to keep it a SHOULD here, but i don't have any strong opinions other than trying to keep things consistent.

@jogu

jogu commented Oct 12, 2026

Copy link
Copy Markdown
Collaborator

One extra complication is that we should at least be clear how this dcql query is processed:

{
  "credentials": [
    {
      "id": "my_credential",
      "format": "mso_mdoc",
      "meta": {
        "doctype_value": "org.iso.18013.5.1.mDL"
      },
      "claims": [
        {
          "id": "age_over_18",
          "path": [
            "org.iso.18013.5.1",
            "age_over_18"
          ]
        },
        {
          "id": "age_in_years",
          "path": [
            "org.iso.18013.5.1",
            "age_in_years"
          ]
        },
        {
          "id": "age_birth_year",
          "path": [
            "org.iso.18013.5.1",
            "age_birth_year"
          ]
        },
        {
          "id": "birth_date",
          "path": [
            "org.iso.18013.5.1",
            "birth_date"
          ]
        }
      ],
      "claim_sets": [
        [
          "age_over_18"
        ],
        [
          "age_in_years"
        ],
        [
          "age_birth_year"
        ],
        [
          "birth_date"
        ]
      ]
    }
  ]
}

In particular in the case where the credential has both age_in_years and age_over_19 (but not age_over_18) which claim is it intended the wallet returns? (I guess a similar question may arise in the ISO 18013-5 query language too, I'm not sure how that handles it but we may want to handle it in a similar/the same way for the sake of everyone's sanity)

@c2bo

c2bo commented Oct 12, 2026

Copy link
Copy Markdown
Member Author

If the wallet supports the matching of age_over_18 to age_over_19 with the logic introduced by this PR, then that is the first option in claim_sets that matches and should be returned imho.

@jogu

jogu commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

So semantically we'd treat it as equivalent to requesting all the age_over_xx values? i.e.

"credentials": [
    {
      "id": "my_credential",
      "format": "mso_mdoc",
      "meta": {
        "doctype_value": "org.iso.18013.5.1.mDL"
      },
      "claims": [
        {
          "id": "age_over_18",
          "path": [
            "org.iso.18013.5.1",
            "age_over_18"
          ]
        },
        {
          "id": "age_over_19",
          "path": [
            "org.iso.18013.5.1",
            "age_over_19"
          ]
        },
...
        {
          "id": "age_over_98",
          "path": [
            "org.iso.18013.5.1",
            "age_over_98"
          ]
        },
        {
          "id": "age_over_99",
          "path": [
            "org.iso.18013.5.1",
            "age_over_99"
          ]
        },
        {
          "id": "age_in_years",
          "path": [
            "org.iso.18013.5.1",
            "age_in_years"
          ]
        },
        {
          "id": "age_birth_year",
          "path": [
            "org.iso.18013.5.1",
            "age_birth_year"
          ]
        },
        {
          "id": "birth_date",
          "path": [
            "org.iso.18013.5.1",
            "birth_date"
          ]
        }
      ],
      "claim_sets": [
        [
          "age_over_18"
        ],
        [
          "age_over_19"
        ],
...
        [
          "age_over_98"
        ],
        [
          "age_over_99"
        ],
        [
          "age_in_years"
        ],
        [
          "age_birth_year"
        ],
        [
          "birth_date"
        ]
      ]
    }
  ]

@c2bo

c2bo commented Oct 15, 2026

Copy link
Copy Markdown
Member Author

So semantically we'd treat it as equivalent to requesting all the age_over_xx values? i.e.

...

Yes, that would be my interpretation - you basically request the first matching one which is identical to your query.

@brentzundel

Copy link
Copy Markdown
Collaborator

Discussed today, language seems acceptable. Needs more approvals to merge. @jogu will review

@jogu

jogu commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

So semantically we'd treat it as equivalent to requesting all the age_over_xx values? i.e.

It turned out my understanding here wasn't correct (thanks to Gareth for explaining the rules better) - the rules in 18013-5 are more complex and an equivalent DCQL query would need value matching as well. i.e.

{
  "credentials": [
    {
      "id": "my_credential",
      "format": "mso_mdoc",
      "meta": { "doctype_value": "org.iso.18013.5.1.mDL" },
      "claims": [
        { "id": "age_over_18", "path": ["org.iso.18013.5.1", "age_over_18"] },
        { "id": "age_over_19", "path": ["org.iso.18013.5.1", "age_over_19"], "values": [true] },
        { "id": "age_over_20", "path": ["org.iso.18013.5.1", "age_over_20"], "values": [true] },
        …
        { "id": "age_over_99", "path": ["org.iso.18013.5.1", "age_over_99"], "values": [true] },
        { "id": "age_over_17", "path": ["org.iso.18013.5.1", "age_over_17"], "values": [false] },
        { "id": "age_over_16", "path": ["org.iso.18013.5.1", "age_over_16"], "values": [false] },
        …
        { "id": "age_over_00", "path": ["org.iso.18013.5.1", "age_over_00"], "values": [false] },
        { "id": "age_in_years", "path": ["org.iso.18013.5.1", "age_in_years"] },
        { "id": "age_birth_year", "path": ["org.iso.18013.5.1", "age_birth_year"] },
        { "id": "birth_date", "path": ["org.iso.18013.5.1", "birth_date"] }
      ],
      "claim_sets": [
        ["age_over_18"],
        ["age_over_19"], ["age_over_20"], …, ["age_over_99"],
        ["age_over_17"], ["age_over_16"], …, ["age_over_00"],
        ["age_in_years"],
        ["age_birth_year"],
        ["birth_date"]
      ]
    }
  ]
}

So for an age_over_18 query, if you get a true claim back (for any age_over_xx), the user is definitely over 18, if you get a false claim back, they're definitely under 18. If the wallet only has age_over_19 false, then in my example query it would return age_in_years instead.

I think that's what Christian's text already says will happen.


### Data Element Selection Rules {#mdocs_data_element_selection}

Document types can define special rules under which a data element other than the one requested can be returned. In particular, [@ISO.18013-5] defines that when an mDL does not contain a requested `age_over_NN` data element, a different `age_over_NN` data element can be returned by the Wallet - see Section 7.2.5 of [@ISO.18013-5] for the definition on how the `age_over_NN` matching works.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think given photo ID (and the age assurance credential too?) have similar rules this is an example:

Suggested change
Document types can define special rules under which a data element other than the one requested can be returned. In particular, [@ISO.18013-5] defines that when an mDL does not contain a requested `age_over_NN` data element, a different `age_over_NN` data element can be returned by the Wallet - see Section 7.2.5 of [@ISO.18013-5] for the definition on how the `age_over_NN` matching works.
Document types can define special rules under which a data element other than the one requested can be returned. For example, [@ISO.18013-5] defines that when an mDL does not contain a requested `age_over_NN` data element, a different `age_over_NN` data element can be returned by the Wallet - see Section 7.2.5 of [@ISO.18013-5] for the definition on how the `age_over_NN` matching works.

* The selected data element is treated as if it were the requested claim when evaluating `claims`, `claim_sets`, and `values` (see (#selecting_claims)). Value matching, if requested, is applied to the value of the selected data element.
* The Presentation contains the data element that was selected under its own data element identifier, not the identifier used in the Claims Query.

Verifiers SHOULD be prepared to receive a different data element identifier and evaluate it according to the document type's rules.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure it's quite right but I think this should be a MUST otherwise it's not clear how it interacts with 'Verifiers MUST check that the returned Credentials meet all criteria in the query.'. Maybe something like this?

Suggested change
Verifiers SHOULD be prepared to receive a different data element identifier and evaluate it according to the document type's rules.
Where the document type they are requesting defines a special rule, Verifiers MUST be prepared to receive a different data element identifier and evaluate it according to the document type's rules.

A claims path pointer can be processed, which means it is applied to a Credential. The results of
processing are the referenced claims.

Credential Format-specific rules as introduced in (#format_specific_parameters) can define special cases in which processing a claims path pointer selects a claim other than the one identified by the direct interpretation of the pointer, especially on a basis of special behaviour for claims in specific credential types.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is slightly more correct, at least according to Americans (who we otherwise follow in this spec):

Suggested change
Credential Format-specific rules as introduced in (#format_specific_parameters) can define special cases in which processing a claims path pointer selects a claim other than the one identified by the direct interpretation of the pointer, especially on a basis of special behaviour for claims in specific credential types.
Credential Format-specific rules as introduced in (#format_specific_parameters) can define special cases in which processing a claims path pointer selects a claim other than the one identified by the direct interpretation of the pointer, especially on the basis of special behavior for claims in specific credential types.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

how to combine DCQL text language with ISO 18013-5 age_over_xx language

6 participants