# Presentation definitions
### Presentation Definitions
The DIF's spec for presentation exchange provides enough horsepower to do some amazing things
https://identity.foundation/presentation-exchange/
----
### Presentation Definitions
We link in presentation definitions using a hash link so you can verify you're using the same version of the presentation definition as when you specified it in your governance
hl:zm9YZpCjPLPJ4Epc:z3TSgaEFFHxY2tsArhUreJ4ixgw9NW7DYuQ9QTPUJFDD
----
### Presentation Definitions
```json!
{
"name": "Trusted Traveler Presentation Definition",
"purpose": "Multi-vaccine and more...",
"comment": "VP, OIDC, DIDComm, or CHAPI outer wrapper here", // Optional
"presentation_definition": {
"id": "32f54163-7166-48f1-93d8-ff217bdb0653", // Required
"submission_requirements": [{ // Optional
"name": "Trusted Traveler Health Proof",
"rule": "pick", // Can be "pick" or "all" only
"count": 1, // We need count only if choose to pick
"from": "Health Proof Options"
}],
```
### Nested submission requirements
```json!
{
"name": "Trusted Traveler Presentation Definition",
"purpose": "Multi-vaccine and more...",
"comment": "VP, OIDC, DIDComm, or CHAPI outer wrapper here",
"presentation_definition": {
"id": "32f54163-7166-48f1-93d8-ff217bdb0653",
"submission_requirements": [
{
"name": "Trusted Traveler",
"rule": "pick",
"count": 1,
"from_nested": [
{
"name": "COVID-19 Health Proof Option",
"rule": "pick",
"count": 1,
"from": "Exemption"
},
{
"name": "COVID-19 Health Proof Option",
"rule": "pick",
"count": 1,
"from": "Vaccine"
},
{
"name": "COVID-19 Health Proof Option",
"rule": "pick",
"count": 1,
"from": "Lab Result"
}
]
}
],
"input_descriptors": [
{
"id": "health_input_1",
"name": "Vaccine_Exemption",
"group": [
"Exemption"
],
"purpose": "stuff",
"schema": [
{
"uri": "RuuJwd3JMffNwZ43DcJKN1:2:Vaccine_Exemption:1.4",
"required": "true"
}
],
...
{
"id": "health_input_2",
"name": "Moderna Vaccination",
"group": [
"Vaccine"
],
"purpose": "stuff",
"schema": [
{
"uri": "RuuJwd3JMffNwZ43DcJKN1:2:Vaccination:1.4",
"required": "true"
}
],
...
{
"id": "health_input_2",
"name": "Pfizer Vaccination",
"group": [
"Vaccine"
],
"purpose": "stuff",
"schema": [
{
"uri": "RuuJwd3JMffNwZ43DcJKN1:2:Vaccination:1.4",
"required": "true"
}
],
...
```
----
### Presentation Definitions
```json!
"input_descriptors": [
{
"id": "health_input_3",
"name": "Lab_Result",
"group": [
"Health Proof Option"
],
"purpose": "stuff",
"schema": [
{
"uri": "RuuJwd3JMffNwZ43DcJKN1:2:Lab_Result:1.4",
"required": "true"
}
],
```
----
### Presentation Definitions
```json!
"constraints": {
"fields": [
{
"path": [
"$.mpid"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_local_id"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_surnames"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_given_names"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_date_of_birth"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_gender_legal"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_street_address"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_city"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_state_province_region"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_postalcode"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_country"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_phone"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_email"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.lab_observation_date_time"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.lab_result"
],
"filter": {
"type": "string",
"oneOf": [
{
"const": "Negative",
"dependent_fields": [
{
"path": [
"$.lab_specimen_collected_date"
],
"filter": {
"type": "string",
"minimum": "today:-:259200"
}
}
]
},
{
"const": "Positive",
"dependent_fields": [
{
"path": [
"$.lab_specimen_collected_date"
],
"filter": {
"type": "string",
"maximum": "today:-:2419200"
}
}
]
}
]
}
},
...
```
### Cartesian product of sets for input desciptors
```json=
...
{
"path": [
"$.lab_result"
],
"filter": {
"type": "string",
"oneOf": [
{
"const": "Negative",
"dependent_fields": [
{
"path": [
"$.lab_specimen_collected_date"
],
"filter": {
"type": "string",
"maximum": "today",
"minimum": "today:-:259200"
}
}
]
},
{
"const": "Positive",
"dependent_fields": [
{
"path": [
"$.lab_specimen_collected_date"
],
"filter": {
"type": "string",
"maximum": "today:-:2419200"
}
}
]
}
]
}
},
...
```
### Code to handle cartesian product of sets
```javascript=
function cartesian(args) {
let result = [],
max = args.length - 1
// Recursive helper function
function helper(arr, i) {
for (let j = 0, l = args[i].length; j < l; j++) {
let a = arr.slice(0) // clone arr
a.push(args[i][j])
if (i == max) {
result.push(a)
} else helper(a, i + 1)
}
}
helper([], 0)
return result
}
```
### Simple input descriptor handler
```javascript=
// (eldersonar) Simple input descriptors handler (no in-field conditions)
const handleSimpleDescriptors = async (
descriptors,
connectionID,
type,
count,
) => {
try {
const uid = uuid()
let attributes = {}
let predicates = {}
attributes[uid] = {
names: [],
}
// attributes[uid].names = []
for (let i = 0; i < descriptors.length; i++) {
const schema_id = descriptors[i].schema[0].uri
const name = descriptors[i].name
const comment = `Requesting Presentation for ${descriptors[i].name}`
const date = Math.floor(Date.now() / 1000)
for (let j = 0; j < descriptors[i].constraints.fields.length; j++) {
const path = descriptors[i].constraints.fields[j].path
.join('')
.split('$.')[1] // (eldersonar) TODO: turn into a loop. This will be not valid if have more than 1 path in the array
// Push descriptors into array
if (descriptors[i].constraints.fields[j].filter.exclusiveMinimum) {
if (
descriptors[i].constraints.fields[
j
].filter.exclusiveMinimum.includes('today:')
) {
predicates[path] = {
p_type: '>',
p_value:
date -
descriptors[i].constraints.fields[
j
].filter.exclusiveMinimum.split(':')[2],
name: path,
restrictions: [
{
schema_id,
},
],
}
} else {
predicates[path] = {
p_type: '>',
p_value: date,
name: path,
restrictions: [
{
schema_id,
},
],
}
}
} else if (descriptors[i].constraints.fields[j].filter.minimum) {
if (
descriptors[i].constraints.fields[j].filter.minimum.includes(
'today:',
)
) {
predicates[path] = {
p_type: '>=',
p_value:
date -
descriptors[i].constraints.fields[j].filter.minimum.split(
':',
)[2],
name: path,
restrictions: [
{
schema_id,
},
],
}
} else {
predicates[path] = {
p_type: '>=',
p_value: date,
name: path,
restrictions: [
{
schema_id,
},
],
}
}
} else if (
descriptors[i].constraints.fields[j].filter.exclusiveMaximum
) {
if (
descriptors[i].constraints.fields[
j
].filter.exclusiveMaximum.includes('today:')
) {
predicates[path] = {
p_type: '<',
p_value:
date -
descriptors[i].constraints.fields[
j
].filter.exclusiveMaximum.split(':')[2],
name: path,
restrictions: [
{
schema_id,
},
],
}
} else {
predicates[path] = {
p_type: '<',
p_value: date,
name: path,
restrictions: [
{
schema_id,
},
],
}
}
} else if (descriptors[i].constraints.fields[j].filter.maximum) {
if (
descriptors[i].constraints.fields[j].filter.maximum.includes(
'today:',
)
) {
predicates[path] = {
p_type: '<=',
p_value:
date -
descriptors[i].constraints.fields[j].filter.maximum.split(
':',
)[2],
name: path,
restrictions: [
{
schema_id,
},
],
}
} else {
predicates[path] = {
p_type: '<=',
p_value: date,
name: path,
restrictions: [
{
schema_id,
},
],
}
}
} else {
// (eldersonar) Prepare attributes and create restrictions
attributes[uid].names.push(path)
attributes[uid].restrictions = [{schema_id: schema_id}]
}
}
// (eldersonar) Assemble presentation request
await createPresentationRequest(
connectionID,
predicates,
attributes,
name,
comment,
type,
count,
)
// (eldersonar) Clear variables at the end of each iteration
attributes = {}
predicates = {}
}
} catch (error) {
console.log(error)
}
}
```
### Request presentation
```javascript!
// Governance presentation request
const requestPresentation = async (connectionID, type, count) => {
console.log(`Requesting Presentation from Connection: ${connectionID}`)
const contact = await Contacts.getContactByConnection(connectionID, [])
// Update traveler's answer to the question
await Travelers.updateProofType(contact.contact_id, type)
let pdf = {}
if (type === 'Vaccination') {
pdf = await Governance.getVaccinePresentationDefinition()
} else if (type === 'Lab') {
pdf = await Governance.getLabPresentationDefinition()
}
const inputDescriptors = pdf.presentation_definition.input_descriptors
try {
const date = Math.floor(Date.now() / 1000)
// (eldersonar) Check if we have submission requirments
if (pdf.presentation_definition.submission_requirements) {
if (
!pdf.presentation_definition.submission_requirements[0].hasOwnProperty(
'from_nested',
)
) {
// Loop through the input descriptors
let i = inputDescriptors.length
// (Eldersonar) Loop through all input descriptors
while (i--) {
// (eldersonar) Execute if there are any of input descriptors match the submission requirements group value
if (
inputDescriptors[i].group.includes(
pdf.presentation_definition.submission_requirements[0].from,
)
) {
let predicateArray = []
let descriptor = {}
descriptor = inputDescriptors[i]
console.log('')
console.log('array of inputDescriptors')
console.log(inputDescriptors)
// (Eldersonar) This flag allows to track which input descriptors needs to be removed from the list
let remove = false
// Loop through all descriptor fields
for (
let j = 0;
j < inputDescriptors[i].constraints.fields.length;
j++
) {
// (Eldersonar) If an input descriptor has some in-field conditional logic
if (inputDescriptors[i].constraints.fields[j].filter.oneOf) {
// (Eldersonar) Get fields with in-field conditional logic
predicateArray.push(
inputDescriptors[i].constraints.fields[j].filter.oneOf,
)
// (Eldersonar) Mark this input descriptor for deletion
remove = true
}
}
// (Eldersonar) Get cartesian sets here
if (predicateArray.length) {
console.log('')
console.log('this is ready to become cartesian set: ')
console.log(predicateArray)
// (Eldersonar) Assign the result of cartesian product of sets to a variable
let cartesianProduct = cartesian(predicateArray, descriptor)
await handleCartesianProductSet(
descriptor,
cartesianProduct,
connectionID,
type,
count,
)
// (Eldersonar) Clear the predicate array before new iteration
predicateArray = []
descriptor = {}
console.log('')
console.log('cartesian product of an array set')
console.log(cartesianProduct)
}
cartesianProduct = []
if (i > -1 && remove) {
inputDescriptors.splice(i, 1)
}
} else {
console.log(
'There are no credentials of group ' +
pdf.presentation_definition.submission_requirements[0].from,
)
}
}
// (eldersonar) TODO: Wrap into an if statement to check if the the rest of the input descriptors are part of the submission requirment group.
await handleSimpleDescriptors(
inputDescriptors,
connectionID,
type,
count,
)
// (eldersonar) Handle nested submission requirments
} else {
console.log(
'...........Handling creating proof requests from the nested submission requirements...........',
)
for (
let g = 0;
g <
pdf.presentation_definition.submission_requirements[0].from_nested
.length;
g++
) {
let chosenDescriptors = []
for (let f = 0; f < inputDescriptors.length; f++) {
if (
inputDescriptors[f].group.includes(
pdf.presentation_definition.submission_requirements[0]
.from_nested[g].from,
)
) {
chosenDescriptors.push(inputDescriptors[f])
}
}
// Loop through the input descriptors
let i = chosenDescriptors.length
// (Eldersonar) Loop through all input descriptors
while (i--) {
// (eldersonar) Execute if there are any of input descriptors match the submission requirements group value
if (
chosenDescriptors[i].group.includes(
pdf.presentation_definition.submission_requirements[0]
.from_nested[g].from,
)
) {
let predicateArray = []
let descriptor = {}
descriptor = chosenDescriptors[i]
// (Eldersonar) This flag allows to track which input descriptors needs to be removed from the list
let remove = false
// Loop through all descriptor fields
for (
let j = 0;
j < chosenDescriptors[i].constraints.fields.length;
j++
) {
// (Eldersonar) If an input descriptor has some in-field conditional logic
if (chosenDescriptors[i].constraints.fields[j].filter.oneOf) {
// (Eldersonar) Get fields with in-field conditional logic
predicateArray.push(
chosenDescriptors[i].constraints.fields[j].filter.oneOf,
)
// (Eldersonar) Mark this input descriptor for deletion
remove = true
}
}
// (Eldersonar) Get cartesian sets here
if (predicateArray.length) {
console.log('')
console.log('this is ready to become cartesian set: ')
console.log(predicateArray)
// (Eldersonar) Assign the result of cartesian product of sets to a variable
let cartesianProduct = cartesian(predicateArray, descriptor)
handleCartesianProductSet(
descriptor,
cartesianProduct,
connectionID,
type,
count,
)
// (Eldersonar) Clear the predicate array before new iteration
predicateArray = []
descriptor = {}
console.log('')
console.log('cartesian product of an array set')
console.log(cartesianProduct)
}
cartesianProduct = []
if (i > -1 && remove) {
chosenDescriptors.splice(i, 1)
}
} else {
console.log(
'There are no credentials of group ' +
pdf.presentation_definition.submission_requirements[0].from,
)
}
}
// (eldersonar) TODO: Wrap into an if statement to check if the the rest of the input descriptors are part of the submission requirment group.
handleSimpleDescriptors(chosenDescriptors, connectionID, type, count)
}
}
}
} catch (error) {
console.error('Error getting proof options')
throw error
}
}
```
### Handling presentations
```javascript=
// Governance message handler
const adminMessage = async (message) => {
console.log('Received Presentations Message', message)
const governance = await Governance.getGovernance()
const privileges = await Governance.getPrivilegesByRoles()
if (message.state === 'verified') {
let endorserDID = null
let schemaID = null
const protocol = 'https://didcomm.org/issue-credential/1.0/'
// Get cred def id and schema id
if (message.presentation && message.presentation.identifiers.length) {
endorserDID = message.presentation.identifiers[0].cred_def_id
.split(':', 1)
.toString()
schemaID = message.presentation.identifiers[0].schema_id
}
// TODO: Check governance and don't send schema id
const participantValidated = await Governance.validateParticipant(
schemaID,
protocol,
endorserDID,
)
// Update traveler's proof status
const contact = await Contacts.getContactByConnection(
message.connection_id,
['Traveler'],
)
let pdf = {}
if (contact.Traveler.dataValues.proof_type === 'Vaccination') {
pdf = await Governance.getVaccinePresentationDefinition()
} else if (contact.Traveler.dataValues.proof_type === 'Lab') {
pdf = await Governance.getLabPresentationDefinition()
} else {
console.log(
"The answer doesn't match any existing presentation exchange files",
)
}
const inputDescriptors = pdf.presentation_definition.input_descriptors
await Travelers.updateProofStatus(contact.contact_id, message.state)
if (message.verified === 'true' && participantValidated) {
let attributes = ''
let predicates = message.presentation.requested_proof.predicates
// (mikekebert) Check the data format to see if the presentation requires the referrant pattern
if (message.presentation.requested_proof.revealed_attr_groups) {
attributes =
message.presentation.requested_proof.revealed_attr_groups[
Object.keys(
message.presentation.requested_proof.revealed_attr_groups,
)[0] // Get first group available
].values // TODO: this needs to be a for-in loop or similar later
} else {
attributes = message.presentation.requested_proof.revealed_attrs
}
const issuerName = await getOrganization()
let credentialVerifiedAttributes = null
if (attributes) {
let credentialAttributes = [
{
name: 'traveler_surnames',
value: attributes.patient_surnames.raw || '',
},
{
name: 'traveler_given_names',
value: attributes.patient_given_names.raw || '',
},
{
name: 'traveler_date_of_birth',
value: attributes.patient_date_of_birth.raw || '',
},
{
name: 'traveler_gender_legal',
value: attributes.patient_gender_legal.raw || '',
},
{
name: 'traveler_country',
value: attributes.patient_country.raw || '',
},
{
name: 'traveler_origin_country',
value: '',
},
{
name: 'traveler_email',
value: attributes.patient_email.raw || '',
},
{
name: 'trusted_traveler_id',
value: uuid(),
},
{
name: 'trusted_traveler_issue_date_time',
value: Math.round(
DateTime.fromISO(new Date()).ts / 1000,
).toString(),
},
{
name: 'trusted_traveler_expiration_date_time',
value: Math.round(
DateTime.local().plus({days: 30}).ts / 1000,
).toString(),
},
{
name: 'governance_applied',
value: governance.name + ' v' + governance.version,
},
{
name: 'credential_issuer_name',
value: issuerName.dataValues.value.organizationName || '',
},
{
name: 'credential_issue_date',
value: Math.round(
DateTime.fromISO(new Date()).ts / 1000,
).toString(),
},
]
// Validation happens here
// (eldersonar) Check if we have submission requirments
if (pdf.presentation_definition.submission_requirements) {
// (eldersonar) Execute if there are any of input descriptors match the submission requirements group value
if (
!pdf.presentation_definition.submission_requirements[0].hasOwnProperty(
'from_nested',
)
) {
for (let i = 0; i < inputDescriptors.length; i++) {
console.log('')
console.log(
`Comparing proof with ${inputDescriptors[i].name} input descriptor`,
)
console.log('')
let fields = []
let proofResult = false
let fieldsValidationResult = false
// (eldersonar) Execute if there are any of input descriptors match the submission requirements group value
if (
inputDescriptors[i].group.includes(
pdf.presentation_definition.submission_requirements[0].from,
)
) {
// Get an array of attributes
for (
let j = 0;
j < inputDescriptors[i].constraints.fields.length;
j++
) {
const fieldPath = inputDescriptors[i].constraints.fields[
j
].path
.join('')
.split('$.')[1] // (eldersonar) TODO: turn into a loop. This will be not valid if have more than 1 path in the array
fields.push(fieldPath)
}
}
// (eldersonar) Get and sort the list of proof attributes and descriptor fields
const proofAttributeKeys = Object.keys(attributes)
const proofPredicateKeys = Object.keys(predicates)
const predicatesAndArrays = proofAttributeKeys.concat(
proofPredicateKeys,
)
const sortedProofFields = predicatesAndArrays.sort(function (
a,
b,
) {
return a.localeCompare(b)
})
const sortedDescriptorFields = fields.sort(function (a, b) {
return a.localeCompare(b)
})
// (eldersonar) Start validation
if (sortedProofFields.length && sortedDescriptorFields.length) {
// (eldersonar) Check if there is no array match (no credential match or no predicate match)
if (
JSON.stringify(sortedProofFields) !=
JSON.stringify(sortedDescriptorFields)
) {
// (eldersonar) Get leftover fields with the filter
let nonDuplicateFields = sortedProofFields.filter(
(val) => !sortedDescriptorFields.includes(val),
)
for (
let k = 0;
k < inputDescriptors[i].constraints.fields.length;
k++
) {
// (eldersonar) Check if input descriptor has in-field conditional logic
if (
inputDescriptors[i].constraints.fields[k].filter.oneOf
) {
for (
let l = 0;
l <
inputDescriptors[i].constraints.fields[k].filter.oneOf
.length;
l++
) {
for (let m = 0; m < nonDuplicateFields.length; m++) {
const prefix = '$.'
let lookupField = ''
lookupField += prefix
lookupField += nonDuplicateFields[m]
// (eldersonar) If we can find the field name in the list of in-field predicates
if (
inputDescriptors[i].constraints.fields[
k
].filter.oneOf[l].dependent_fields[0].path.includes(
lookupField,
)
) {
// (eldersonar) Removing predicate from the list of sorted fields
const index = sortedProofFields.indexOf(
nonDuplicateFields[m],
)
if (index > -1) {
sortedProofFields.splice(index, 1)
}
console.log(sortedProofFields)
console.log(sortedDescriptorFields)
console.log(
JSON.stringify(sortedProofFields) ===
JSON.stringify(sortedDescriptorFields),
)
// (eldersonar) Check if arrays match after the predicates were removed
if (
JSON.stringify(sortedProofFields) ===
JSON.stringify(sortedDescriptorFields)
) {
console.log('')
console.log(
'_____________________________________________',
)
console.log('Validation of proof was successful.')
fieldsValidationResult = validateFieldByField(
attributes,
inputDescriptors[i],
)
proofResult = true
} else {
console.log('Validation failed.')
proofResult = false
}
} else {
// console.log("Validation failed. No match was found.")
proofResult = false
}
}
}
}
}
}
// (eldersonar) Perfect match, proof fields are validated!
else {
console.log('')
console.log('_____________________________________________')
console.log('Validation of proof was successful.')
fieldsValidationResult = validateFieldByField(
attributes,
inputDescriptors[i],
)
proofResult = true
}
} else {
console.log('Error: lacking data for validation')
}
console.log('')
console.log('Validation of proof status is: ', proofResult)
console.log(
'Field-by-field validation status is: ',
fieldsValidationResult,
)
// Check if all level validation passed
if (proofResult && fieldsValidationResult) {
...
```
### Field by field validation
```javascript=
const validateFieldByField = (attributes, inputDescriptor) => {
// (eldersonar) Value validation happens here
let result = null
let typePass = false
let formatPass = null
let valuePass = false
let patternPass = false
for (let key in attributes) {
if (attributes.hasOwnProperty(key)) {
console.log('')
console.log(key + ' -> ' + attributes[key].raw)
// Create prefixed attribute key
const prefix = '$.'
let prefixedKey = ''
prefixedKey += prefix
prefixedKey += key
for (let p = 0; p < inputDescriptor.constraints.fields.length; p++) {
// (eldersonar) Validate if field can be found
if (inputDescriptor.constraints.fields[p].path.includes(prefixedKey)) {
// (eldersonar) Type validation
if (inputDescriptor.constraints.fields[p].filter.type) {
switch (inputDescriptor.constraints.fields[p].filter.type) {
case 'string':
// Support empty string && attributes[key].raw !== ""
if (typeof attributes[key].raw === 'string') {
// console.log('the type check (STRING) have passed')
typePass = true
} else {
console.log('this is NOT A STRING or STRING IS EMPTY')
typePass = false
break
}
break
case 'number':
if (!isNaN(attributes[key].raw)) {
// console.log('the type check (NUMBER) have passed')
typePass = true
} else {
console.log('this is NOT A NUMBER')
typePass = false
break
}
break
case 'boolean':
if (
attributes[key].raw === 'true' ||
attributes[key].raw === 'false'
) {
// console.log('the type check (BOOLEAN) have passed')
typePass = true
} else {
console.log('this is NOT A BOOLEAN')
typePass = false
break
}
break
default:
console.log('Error: The type check failed')
typePass = false
break
}
} else {
// console.log('no type was found for this attribute')
typePass = true
}
// (eldersonar) Format validation
if (inputDescriptor.constraints.fields[p].filter.format) {
let dateNumber = parseInt(attributes[key].raw, 10)
// (eldersonar) Check if the value can be transformed to a valid number
if (attributes[key].raw === '') {
// console.log('format passed')
formatPass = true
} else if (!isNaN(dateNumber)) {
// console.log('the date check (NUMBER) have passed')
let luxonDate = DateTime.fromMillis(dateNumber).toISO()
let date = new DateTime(luxonDate).isValid
// (eldersonar) Check if the valid Luxon datetime format
if (date) {
// console.log('the date is: ', date)
// console.log('format passed')
formatPass = true
} else {
// console.log('this is NOT A DATE')
console.log('format failed')
formatPass = false
break
}
} else {
// console.log('this is NOT A DATE')
console.log('format failed')
formatPass = false
break
}
} else {
// console.log('no format was found for this attribute')
formatPass = true
}
// (eldersonar) Value validation
if (inputDescriptor.constraints.fields[p].filter.const) {
// (eldersonar) Check if the value is a number datatype
if (!isNaN(inputDescriptor.constraints.fields[p].filter.const)) {
const stringNumber =
'' + inputDescriptor.constraints.fields[p].filter.const
if (attributes[key].raw === stringNumber) {
// console.log('value passed')
valuePass = true
} else {
console.log('value failed')
valuePass = false
break
}
} else {
if (
attributes[key].raw ===
inputDescriptor.constraints.fields[p].filter.const
) {
// console.log('value passed')
valuePass = true
} else {
console.log('value failed')
valuePass = false
break
}
}
} else {
// console.log('no value was found for this attribute')
valuePass = true
}
// (eldersonar) Pattern validation
if (inputDescriptor.constraints.fields[p].filter.pattern) {
// Check if it's base64 encoded
if (attributes[key].raw === '') {
// console.log('pattern passed')
patternPass = true
} else if (
Buffer.from(
inputDescriptor.constraints.fields[p].filter.pattern,
'base64',
).toString('base64') ===
inputDescriptor.constraints.fields[p].filter.pattern
) {
// console.log('decoding....')
const decodedPattern = Util.decodeBase64(
inputDescriptor.constraints.fields[p].filter.pattern,
)
const re = new RegExp(decodedPattern)
// (eldersonar) Test pattern
if (re.test(attributes[key].raw)) {
// console.log('pattern passed')
patternPass = true
} else {
console.log('pattern failed')
patternPass = false
break
}
// If not base64 encoded
} else {
const re = new RegExp(
inputDescriptor.constraints.fields[p].filter.pattern,
)
// (eldersonar) Test pattern
if (re.test(attributes[key].raw)) {
// console.log('pattern passed')
patternPass = true
} else {
console.log('pattern failed')
patternPass = false
break
}
}
} else {
// console.log('no pattern was found for this attribute')
patternPass = true
}
}
}
}
// Break out of outer loop if validation failed
if (!typePass || !valuePass || !patternPass || !formatPass) {
result = false
break
} else {
result = true
}
}
return result
}
```
### Full file example
```json=
{
"name": "Trusted Traveler Presentation Definition",
"purpose": "Multi-vaccine and more...",
"comment": "VP, OIDC, DIDComm, or CHAPI outer wrapper here",
"presentation_definition": {
"id": "32f54163-7166-48f1-93d8-ff217bdb0653",
"submission_requirements": [
{
"name": "Trusted Traveler Health Proof",
"rule": "pick",
"count": 1,
"from": "Health Proof Option"
}
],
"input_descriptors": [
{
"id": "health_input_1",
"name": "Vaccine_Exemption",
"group": [
"Health Proof Option"
],
"purpose": "stuff",
"schema": [
{
"uri": "RuuJwd3JMffNwZ43DcJKN1:2:Vaccine_Exemption:1.4",
"required": "true"
}
],
"constraints": {
"fields": [
{
"path": [
"$.mpid"
],
"id": "12345", // Optional
"purpose": "Master patient identifier of source that wrote the record to the ledger", // Optional
"filter": { // Required
"predicate": "required", // Optional
"type": "string", // Required
"pattern": "did:example:gov1|did:example:gov2" // Optional
}
},
{
"path": [
"$.credentialSubject.patient_local_id", // Normalizing the differences in structure between JSON-LD/JWT-based Verifiable Credentials and vanilla JSON Web Tokens (JWTs) [RFC7519].
"$.vc.credentialSubject.patient_local_id",
"$.patient_local_id"
],
"filter": {
"type": "number",
"pattern": "^[0-9]{9}|^([a-zA-Z]){4}([a-zA-Z]){2}([0-9a-zA-Z]){2}([0-9a-zA-Z]{3})?$" // Optional
}
},
{
"path": [
"$.patient_surnames"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_given_names"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_surnames"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_date_of_birth"
],
"filter": {
"type": "string",
"format": "date"
}
},
{
"path": [
"$.patient_gender_legal"
],
"filter": {
"type": "string",
"pattern": ""
}
},
{
"path": [
"$.patient_street_address"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_city"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_state_province_region"
],
"filter": {
"type": "string",
"pattern": ""
}
},
{
"path": [
"$.patient_postalcode"
],
"filter": {
"type": "string",
"pattern": ""
}
},
{
"path": [
"$.patient_country"
],
"filter": {
"type": "string",
"pattern": ""
}
},
{
"path": [
"$.patient_phone"
],
"filter": {
"type": "number",
"pattern": ""
}
},
{
"path": [
"$.patient_surnames"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_email"
],
"filter": {
"type": "string",
"pattern": ""
}
},
{
"path": [
"$.exemption_record_id"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.exemption_requestor"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.exemption_requestor_relationship"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.exemption_issue_date"
],
"filter": {
"type": "string",
"format": "date"
}
},
{
"path": [
"$.exemption_state_province_region"
],
"filter": {
"type": "string",
"pattern": ""
}
},
{
"path": [
"$.exemption_country"
],
"filter": {
"type": "string",
"pattern": ""
}
},
{
"path": [
"$.exemption_type"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.exemption_medical_permanent"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.exemption_note"
],
"filter": {
"type": "boolean",
"pattern": "true"
}
},
{
"path": [
"$.exemption_from_all"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_surnames"
],
"filter": {
"type": "boolean",
"pattern": "true"
}
},
{
"path": [
"$.exemption_diseases_code"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.exemption_disease_code_qualifier"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.exemption_disease_code_name"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.exemption_medical_physician_surnames"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.exemption_medical_physician_given_names"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.exemption_medical_physician_full_name"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.exemption_medical_physician_license_number"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.exemption_medical_physician_license_type"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.exemption_medical_physician_license_state_province_region"
],
"filter": {
"type": "string",
"pattern": ""
}
},
{
"path": [
"$.exemption_medical_physician_license_country"
],
"filter": {
"type": "string",
"pattern": ""
}
},
{
"path": [
"$.exemption_expiration_date"
],
"filter": {
"type": "string",
"format": "date",
"exclusiveMinimum": "today",
"required": "true"
}
},
{
"path": [
"$.exemption_credential_issuer"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.certificate_original_issuer"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.certificate_original_identifier"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.credential_issuer_name"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.credential_issue_date"
],
"filter": {
"type": "string",
"format": "date"
}
}
]
}
},
{
"id": "health_input_2",
"name": "Vaccination",
"group": [
"Health Proof Option"
],
"purpose": "stuff",
"schema": [
{
"uri": "RuuJwd3JMffNwZ43DcJKN1:2:Vaccination:1.4",
"required": "true"
}
],
"constraints": {
"fields": [
{
"path": [
"$.mpid"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_local_id"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.sending_facility"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_surnames"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_given_names"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_date_of_birth"
],
"filter": {
"type": "string",
"format": "date"
}
},
{
"path": [
"$.patient_gender_legal"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_street_address"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_city"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_state_province_region"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_postalcode"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_country"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_phone"
],
"filter": {
"type": "number",
"pattern": ""
}
},
{
"path": [
"$.patient_email"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_record_id"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_administration_facility_id"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_administration_facility_id_qualifier"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_administration_facility_name"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_administration_state_province_region"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_administration_postalcode"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_administration_country"
],
"filter": {
"type": "string",
"pattern": "^[0-9]{9}|^([a-zA-Z]){4}([a-zA-Z]){2}([0-9a-zA-Z]){2}([0-9a-zA-Z]{3})?$"
}
},
{
"path": [
"$.vaccine_administration_date"
],
"filter": {
"type": "string",
"exclusiveMaximum": "today:-:1209600"
}
},
{
"path": [
"$.vaccine_dose_number"
],
"filter": {
"type": "number"
}
},
{
"path": [
"$.vaccine_series_complete"
],
"filter": {
"const": "true",
"type": "boolean",
"pattern": "true"
}
},
{
"path": [
"$.vaccine_lot_number"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_code"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_code_qualifier"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_code_name"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_manufacturer_code"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_manufacturer_code_qualifier"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_manufacturer_code_name"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_disease_target_code"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_disease_target_code_qualifier"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_disease_target_name"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_administration_provider_id"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_administration_provider_id_qualifier"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_administration_provider_fullname"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.vaccine_education_reference_material"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.certificate_original_issuer"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.certificate_original_identifier"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.credential_issuer_name"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.credential_issue_date"
],
"filter": {
"type": "string",
"format": "date"
}
}
]
}
},
{
"id": "health_input_3",
"name": "Lab_Result",
"group": [
"Health Proof Option"
],
"purpose": "stuff",
"schema": [
{
"uri": "RuuJwd3JMffNwZ43DcJKN1:2:Lab_Result:1.4",
"required": "true"
}
],
"constraints": {
"fields": [
{
"path": [
"$.mpid"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_local_id"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_surnames"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_given_names"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_date_of_birth"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_gender_legal"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_street_address"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_city"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_state_province_region"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_postalcode"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_country"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_phone"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.patient_email"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.lab_observation_date_time"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.lab_result"
],
"filter": {
"type": "string",
"oneOf": [
{
"const": "Negative",
"dependent_fields": [
{
"path": [
"$.lab_specimen_collected_date"
],
"filter": {
"type": "string",
"minimum": "today:-:259200"
}
}
]
},
{
"const": "Positive",
"dependent_fields": [
{
"path": [
"$.lab_specimen_collected_date"
],
"filter": {
"type": "string",
"maximum": "today:-:2419200"
}
}
]
}
]
}
},
{
"path": [
"$.lab_specimen_type"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.lab_result_status"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.lab_coding_qualifier"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.lab_code"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.lab_description"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.lab_order_id"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.lab_normality"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.lab_comment"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.ordering_facility_id"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.ordering_facility_id_qualifier"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.ordering_facility_name"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.ordering_facility_state_province_region"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.ordering_facility_postalcode"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.ordering_facility_country"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.performing_laboratory_id"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.performing_laboratory_id_qualifier"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.performing_laboratory_name"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.performing_laboratory_state_province_region"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.performing_laboratory_postalcode"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.performing_laboratory_country"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.lab_performed_by"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.credential_issuer_name"
],
"filter": {
"type": "string"
}
},
{
"path": [
"$.credential_issue_date"
],
"filter": {
"type": "string"
}
}
]
}
}
]
}
}
```