diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ca1cddee..f40e6144 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,14 +12,14 @@ jobs: name: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: 8 - name: Use Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '18.x' cache: 'pnpm' @@ -31,7 +31,7 @@ jobs: - name: pnpm test run: pnpm test - name: codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos name: codecove # optional diff --git a/lib/PEX.ts b/lib/PEX.ts index 6c391965..37cce6d4 100644 --- a/lib/PEX.ts +++ b/lib/PEX.ts @@ -6,6 +6,7 @@ import { ICredential, IPresentation, IProof, + JwtDecodedVerifiableCredential, OriginalVerifiableCredential, OriginalVerifiablePresentation, OrPromise, @@ -17,8 +18,7 @@ import { } from '@sphereon/ssi-types'; import { Status } from './ConstraintUtils'; -import { EvaluationClientWrapper, EvaluationResults, SelectResults } from './evaluation'; -import { PresentationEvaluationResults } from './evaluation'; +import { EvaluationClientWrapper, EvaluationResults, PresentationEvaluationResults, SelectResults } from './evaluation'; import { PartialSdJwtDecodedVerifiableCredential, PartialSdJwtKbJwt, @@ -106,7 +106,7 @@ export class PEX { let presentationSubmission = opts?.presentationSubmission; let presentationSubmissionLocation = opts?.presentationSubmissionLocation ?? - (Array.isArray(presentations) || !CredentialMapper.isW3cPresentation(wrappedPresentations[0].presentation) + ((Array.isArray(presentations) && presentations.length > 1) || !CredentialMapper.isW3cPresentation(wrappedPresentations[0].presentation) ? PresentationSubmissionLocation.EXTERNAL : PresentationSubmissionLocation.PRESENTATION); @@ -290,21 +290,21 @@ export class PEX { opts?.presentationSubmissionLocation ?? (hasSdJwtCredentials ? PresentationSubmissionLocation.EXTERNAL : PresentationSubmissionLocation.PRESENTATION); - const presentation = PEX.constructPresentation(selectedCredentials, { + const presentations = this.constructPresentations(selectedCredentials, { ...opts, // We only pass in the submission in case it needs to be included in the presentation presentationSubmission: presentationSubmissionLocation === PresentationSubmissionLocation.PRESENTATION ? presentationSubmission : undefined, hasher: this.options?.hasher, }); - + this.updateSdJwtCredentials(presentations); return { - presentation, + presentations, presentationSubmissionLocation, presentationSubmission, }; } - public static constructPresentation( + public constructPresentations( selectedCredentials: OriginalVerifiableCredential | OriginalVerifiableCredential[], opts?: { presentationSubmission?: PresentationSubmission; @@ -315,108 +315,123 @@ export class PEX { */ hasher?: Hasher; }, - ): IPresentation | PartialSdJwtDecodedVerifiableCredential { - const credentials = Array.isArray(selectedCredentials) ? selectedCredentials : [selectedCredentials]; - - // for SD-JWT we want to return the SD-JWT with only the needed disclosures (so filter disclosures array, and update the compactSdJwt) - // in addition we want to create the KB-JWT payload as well. - // FIXME: include the KB-JWT payload? - if (credentials.some((c) => CredentialMapper.isSdJwtDecodedCredential(c) || CredentialMapper.isSdJwtEncoded(c))) { - if (credentials.length > 1) { - // Until there's some consensus around the following issue, we'll only support a single - // SD-JWT credential in a presentation - // https://github.com/decentralized-identity/presentation-exchange/issues/462 - throw new Error('Only a single credential is supported when creating a presentation with an SD-JWT VC'); - } - - if (opts?.presentationSubmission) { - throw new Error('Presentation submission cannot be included in the presentation when creating a presentation with an SD-JWT VC'); - } - - if (opts?.basePresentationPayload) { - throw new Error('Base presentation payload cannot be when creating a presentation from an SD-JWT VC'); - } - - // NOTE: we assume the credential already has selective disclosure applied, even if it is encoded. Is - // that a valid assumption? It seems to be this way for BBS SD as well - const decoded = ( - CredentialMapper.isSdJwtEncoded(credentials[0]) ? CredentialMapper.decodeVerifiableCredential(credentials[0], opts?.hasher) : credentials[0] - ) as SdJwtDecodedVerifiableCredential; - - if (!opts?.hasher) { + ): Array { + if (!selectedCredentials) { + throw Error(`At least a verifiable credential needs to be passed in to create a presentation`); + } + const verifiableCredential = (Array.isArray(selectedCredentials) ? selectedCredentials : [selectedCredentials]) as W3CVerifiableCredential[]; + if (verifiableCredential.some((c) => CredentialMapper.isSdJwtDecodedCredential(c) || CredentialMapper.isSdJwtEncoded(c))) { + if (!this.options?.hasher) { throw new Error('Hasher must be provided when creating a presentation with an SD-JWT VC'); } + } - // extract sd_alg or default to sha-256 - const hashAlg = decoded.signedPayload._sd_alg ?? 'sha-256'; - const sdHash = calculateSdHash(decoded.compactSdJwtVc, hashAlg, opts.hasher); - - const kbJwt = { - // alg MUST be set by the signer - header: { - typ: 'kb+jwt', - // aud MUST be set by the signer or provided by e.g. SIOP/OpenID4VP lib - }, - payload: { - iat: new Date().getTime(), - sd_hash: sdHash, - }, - } satisfies PartialSdJwtKbJwt; + const wVCs = verifiableCredential.map((vc) => CredentialMapper.toWrappedVerifiableCredential(vc, { hasher: this.options?.hasher })); + const holders = Array.from(new Set(wVCs.flatMap((wvc) => getSubjectIdsAsString(wvc.credential as ICredential)))); + if (holders.length !== 1 && !opts?.holderDID) { + console.log( + `We deduced ${holders.length} subject from ${wVCs.length} Verifiable Credentials, and no holder property was given. This might lead to undesired results`, + ); + } + const holder = opts?.holderDID ?? (holders.length === 1 ? holders[0] : undefined); + + const type = opts?.basePresentationPayload?.type + ? Array.isArray(opts.basePresentationPayload.type) + ? opts.basePresentationPayload.type + : [opts.basePresentationPayload.type] + : []; + if (!type.includes('VerifiablePresentation')) { + type.push('VerifiablePresentation'); + } - const sdJwtDecodedPresentation: PartialSdJwtDecodedVerifiableCredential = { - ...decoded, - kbJwt, - }; - return sdJwtDecodedPresentation; - } else { - if (!selectedCredentials) { - throw Error(`At least a verifiable credential needs to be passed in to create a presentation`); - } - const verifiableCredential = (Array.isArray(selectedCredentials) ? selectedCredentials : [selectedCredentials]) as W3CVerifiableCredential[]; - const wVCs = verifiableCredential.map((vc) => CredentialMapper.toWrappedVerifiableCredential(vc)); - const holders = Array.from(new Set(wVCs.flatMap((wvc) => getSubjectIdsAsString(wvc.credential as ICredential)))); - if (holders.length !== 1 && !opts?.holderDID) { - console.log( - `We deduced ${holders.length} subject from ${wVCs.length} Verifiable Credentials, and no holder property was given. This might lead to undesired results`, - ); - } - const holder = opts?.holderDID ?? (holders.length === 1 ? holders[0] : undefined); - - const type = opts?.basePresentationPayload?.type - ? Array.isArray(opts.basePresentationPayload.type) - ? opts.basePresentationPayload.type - : [opts.basePresentationPayload.type] - : []; - if (!type.includes('VerifiablePresentation')) { - type.push('VerifiablePresentation'); - } + const context = opts?.basePresentationPayload?.['@context'] + ? Array.isArray(opts.basePresentationPayload['@context']) + ? opts.basePresentationPayload['@context'] + : [opts.basePresentationPayload['@context']] + : []; + if (!context.includes('https://www.w3.org/2018/credentials/v1')) { + context.push('https://www.w3.org/2018/credentials/v1'); + } - const context = opts?.basePresentationPayload?.['@context'] - ? Array.isArray(opts.basePresentationPayload['@context']) - ? opts.basePresentationPayload['@context'] - : [opts.basePresentationPayload['@context']] - : []; - if (!context.includes('https://www.w3.org/2018/credentials/v1')) { - context.push('https://www.w3.org/2018/credentials/v1'); + if (opts?.presentationSubmission) { + if (!type.includes('PresentationSubmission')) { + type.push('PresentationSubmission'); } - - if (opts?.presentationSubmission) { - if (!type.includes('PresentationSubmission')) { - type.push('PresentationSubmission'); - } - if (!context.includes('https://identity.foundation/presentation-exchange/submission/v1')) { - context.push('https://identity.foundation/presentation-exchange/submission/v1'); - } + if (!context.includes('https://identity.foundation/presentation-exchange/submission/v1')) { + context.push('https://identity.foundation/presentation-exchange/submission/v1'); } - return { + } + const result: Array = []; + if (PEX.allowMultipleVCsPerPresentation(verifiableCredential)) { + result.push({ ...opts?.basePresentationPayload, '@context': context, type, holder, ...(!!opts?.presentationSubmission && { presentation_submission: opts.presentationSubmission }), verifiableCredential, - }; + }); + } else { + verifiableCredential.forEach((vc) => { + if (CredentialMapper.isSdJwtDecodedCredential(vc)) { + result.push(vc as PartialSdJwtDecodedVerifiableCredential); + } else if (CredentialMapper.isSdJwtEncoded(vc)) { + const decoded = CredentialMapper.decodeVerifiableCredential(vc, opts?.hasher); + result.push(decoded as PartialSdJwtDecodedVerifiableCredential); + } else { + // This should be jwt or json-ld + result.push({ + ...opts?.basePresentationPayload, + '@context': context, + type, + holder, + ...(!!opts?.presentationSubmission && { presentation_submission: opts.presentationSubmission }), + verifiableCredential: [vc], + }); + } + }); } + return result; + } + + /* + TODO SDK-37 refinement needed + */ + private static allowMultipleVCsPerPresentation(verifiableCredentials: Array): boolean { + const jwtCredentials = verifiableCredentials.filter((c) => CredentialMapper.isJwtEncoded(c) || CredentialMapper.isJwtDecodedCredential(c)); + + if (jwtCredentials.length > 0) { + const subjects = new Set(); + const verificationMethods = new Set(); + + for (const credential of jwtCredentials) { + const decodedCredential = CredentialMapper.isJwtEncoded(credential) + ? (CredentialMapper.decodeVerifiableCredential(credential) as JwtDecodedVerifiableCredential) + : (credential as JwtDecodedVerifiableCredential); + + const subject = + decodedCredential.sub || + (decodedCredential.vc && 'id' in decodedCredential.vc.credentialSubject && decodedCredential.vc.credentialSubject.id); + if (subject) { + subjects.add(subject); + } + + const vcProof = decodedCredential.proof ?? decodedCredential.vc.proof; + const proofs = Array.isArray(vcProof) ? vcProof : [vcProof]; + proofs.filter((proof: IProof) => proof.verificationMethod).forEach((proof: IProof) => verificationMethods.add(proof.verificationMethod)); + } + + // If there's more than one unique subject or verification method, we can't allow multiple VCs in a single presentation + if (subjects.size > 1 || verificationMethods.size > 1) { + return false; + } + } + + if (verifiableCredentials.some((c) => CredentialMapper.isSdJwtEncoded(c) || CredentialMapper.isSdJwtDecodedCredential(c))) { + return false; + } + + return true; } /** @@ -504,7 +519,8 @@ export class PEX { }); const presentationResult = this.presentationFrom(presentationDefinition, evaluationResult.verifiableCredential, opts); - const evaluationResults = this.evaluatePresentation(presentationDefinition, presentationResult.presentation, { + const presentations = presentationResult.presentations; + const evaluationResults = this.evaluatePresentation(presentationDefinition, presentations, { limitDisclosureSignatureSuites, ...(presentationResult.presentationSubmissionLocation === PresentationSubmissionLocation.EXTERNAL && { presentationSubmission: presentationResult.presentationSubmission, @@ -529,59 +545,68 @@ export class PEX { domain: proofOptions?.domain, }; - let presentation = presentationResult.presentation; - - // Select type without kbJwt as isSdJwtDecodedCredential and won't accept the partial sdvc type - if (CredentialMapper.isSdJwtDecodedCredential(presentationResult.presentation as SdJwtDecodedVerifiableCredential)) { - const sdJwtPresentation = presentation as SdJwtDecodedVerifiableCredential; - if (!this.options?.hasher) { - throw new Error('Hasher must be provided when creating a presentation with an SD-JWT VC'); - } - - // extract sd_alg or default to sha-256 - const hashAlg = presentationResult.presentation.signedPayload._sd_alg ?? 'sha-256'; - const sdHash = calculateSdHash(presentationResult.presentation.compactSdJwtVc, hashAlg, this.options.hasher); + this.updateSdJwtCredentials(presentations, proofOptions?.nonce); - const kbJwt = { - // alg MUST be set by the signer - header: { - typ: 'kb+jwt', + const verifiablePresentations: Array = []; + for (const presentation of presentations) { + const callBackParams: PresentationSignCallBackParams = { + options: { + ...opts, + presentationSubmissionLocation: presentationResult.presentationSubmissionLocation, }, - // aud MUST be set by the signer or provided by e.g. SIOP/OpenID4VP lib - payload: { - iat: new Date().getTime(), - nonce: proofOptions?.nonce, - sd_hash: sdHash, - }, - } satisfies PartialSdJwtKbJwt; - - presentation = { - ...sdJwtPresentation, - kbJwt, - } satisfies PartialSdJwtDecodedVerifiableCredential; + presentation, + presentationDefinition, + selectedCredentials, + proof, + presentationSubmission: evaluationResults.value, + evaluationResults, + }; + verifiablePresentations.push(await signingCallBack(callBackParams)); } - - const callBackParams: PresentationSignCallBackParams = { - options: { - ...opts, - presentationSubmissionLocation: presentationResult.presentationSubmissionLocation, - }, - presentation, - presentationDefinition, - selectedCredentials, - proof, - presentationSubmission: evaluationResults.value, - evaluationResults, - }; - const verifiablePresentation = await signingCallBack(callBackParams); - return { - verifiablePresentation, + verifiablePresentations, presentationSubmissionLocation: presentationResult.presentationSubmissionLocation, presentationSubmission: evaluationResults.value, }; } + private updateSdJwtCredentials( + presentations: Array, + nonce?: string, + ) { + presentations.forEach((presentation, index) => { + // Select type without kbJwt as isSdJwtDecodedCredential and won't accept the partial sdvc type + if (CredentialMapper.isSdJwtDecodedCredential(presentation as SdJwtDecodedVerifiableCredential)) { + const sdJwtCredential = presentation as SdJwtDecodedVerifiableCredential; + if (!this.options?.hasher) { + throw new Error('Hasher must be provided when creating a presentation with an SD-JWT VC'); + } + + // extract sd_alg or default to sha-256 + const hashAlg = sdJwtCredential.signedPayload._sd_alg ?? 'sha-256'; + const sdHash = calculateSdHash(sdJwtCredential.compactSdJwtVc, hashAlg, this.options.hasher); + + const kbJwt = { + // alg MUST be set by the signer + header: { + typ: 'kb+jwt', + }, + // aud MUST be set by the signer or provided by e.g. SIOP/OpenID4VP lib + payload: { + iat: Math.floor(new Date().getTime() / 1000), + nonce: nonce, + sd_hash: sdHash, + }, + } satisfies PartialSdJwtKbJwt; + + presentations[index] = { + ...sdJwtCredential, + kbJwt, + } satisfies PartialSdJwtDecodedVerifiableCredential; + } + }); + } + public static definitionVersionDiscovery(presentationDefinition: IPresentationDefinition): DiscoveredVersion { return definitionVersionDiscovery(presentationDefinition); } diff --git a/lib/PEXv1.ts b/lib/PEXv1.ts index 6853eb8c..b0175682 100644 --- a/lib/PEXv1.ts +++ b/lib/PEXv1.ts @@ -124,13 +124,13 @@ export class PEXv1 extends PEX { opts?.presentationSubmissionLocation ?? (hasSdJwtCredentials ? PresentationSubmissionLocation.EXTERNAL : PresentationSubmissionLocation.PRESENTATION); - const presentation = PEX.constructPresentation(selectedCredentials, { + const presentations = this.constructPresentations(selectedCredentials, { ...opts, presentationSubmission: presentationSubmissionLocation === PresentationSubmissionLocation.PRESENTATION ? presentationSubmission : undefined, }); return { - presentation, + presentations, presentationSubmissionLocation, presentationSubmission, }; diff --git a/lib/PEXv2.ts b/lib/PEXv2.ts index 03e9d45b..13795883 100644 --- a/lib/PEXv2.ts +++ b/lib/PEXv2.ts @@ -15,7 +15,7 @@ export class PEXv2 extends PEX { * The evaluatePresentationV2 compares what is expected from a presentation with a presentationDefinitionV2. * * @param presentationDefinition the definition of what is expected in the presentation. - * @param presentation the presentation which has to be evaluated in comparison of the definition. + * @param presentations the presentation which has to be evaluated in comparison of the definition. * @param opts - limitDisclosureSignatureSuites the credential signature suites that support limit disclosure * * @return the evaluation results specify what was expected and was fulfilled and also specifies which requirements described in the input descriptors @@ -120,13 +120,13 @@ export class PEXv2 extends PEX { opts?.presentationSubmissionLocation ?? (hasSdJwtCredentials ? PresentationSubmissionLocation.EXTERNAL : PresentationSubmissionLocation.PRESENTATION); - const presentation = PEX.constructPresentation(selectedCredentials, { + const presentations = this.constructPresentations(selectedCredentials, { ...opts, presentationSubmission: presentationSubmissionLocation === PresentationSubmissionLocation.PRESENTATION ? presentationSubmission : undefined, }); return { - presentation, + presentations, presentationSubmissionLocation, presentationSubmission, }; diff --git a/lib/evaluation/core/evaluationResults.ts b/lib/evaluation/core/evaluationResults.ts index 43b84a6d..95928bf6 100644 --- a/lib/evaluation/core/evaluationResults.ts +++ b/lib/evaluation/core/evaluationResults.ts @@ -2,10 +2,9 @@ import { PresentationSubmission } from '@sphereon/pex-models'; import { IPresentation, IVerifiableCredential, OriginalVerifiablePresentation, SdJwtDecodedVerifiableCredential } from '@sphereon/ssi-types'; import { Checked, Status } from '../../ConstraintUtils'; -import { OrArray } from '../../types'; export interface PresentationEvaluationResults extends Omit { - presentation: OrArray; + presentations: Array; } export interface EvaluationResults { diff --git a/lib/evaluation/evaluationClientWrapper.ts b/lib/evaluation/evaluationClientWrapper.ts index 4c16c280..0e2cf9d2 100644 --- a/lib/evaluation/evaluationClientWrapper.ts +++ b/lib/evaluation/evaluationClientWrapper.ts @@ -4,6 +4,7 @@ import type { SubmissionRequirement } from '@sphereon/pex-models'; import { CredentialMapper, IVerifiableCredential, + IVerifiablePresentation, OriginalVerifiableCredential, SdJwtDecodedVerifiableCredential, WrappedVerifiableCredential, @@ -96,7 +97,11 @@ export class EvaluationClientWrapper { marked, ); } catch (e) { - const matchingError: Checked = { status: Status.ERROR, message: JSON.stringify(e), tag: 'matchSubmissionRequirements' }; + const matchingError: Checked = { + status: Status.ERROR, + message: JSON.stringify(e), + tag: 'matchSubmissionRequirements', + }; return { errors: errors ? [...errors, matchingError] : [matchingError], warnings: warnings, @@ -406,7 +411,7 @@ export class EvaluationClientWrapper { const result: PresentationEvaluationResults = { areRequiredCredentialsPresent: Status.INFO, - presentation: Array.isArray(wvps) ? wvps.map((wvp) => wvp.original) : wvps.original, + presentations: Array.isArray(wvps) ? wvps.map((wvp) => wvp.original) : [wvps.original], errors: [], warnings: [], }; @@ -429,7 +434,9 @@ export class EvaluationClientWrapper { if (this._client.generatePresentationSubmission && result.value && useExternalSubmission) { // we map the descriptors of the generated submisison to take into account the nexted values result.value.descriptor_map = result.value.descriptor_map.map((descriptor) => { - const [wvcResult] = JsonPathUtils.extractInputField(allWvcs, [descriptor.path]) as Array<{ value: WrappedVerifiableCredential }>; + const [wvcResult] = JsonPathUtils.extractInputField(allWvcs, [descriptor.path]) as Array<{ + value: WrappedVerifiableCredential; + }>; if (!wvcResult) { throw new Error(`Could not find descriptor path ${descriptor.path} in wrapped verifiable credentials`); } @@ -460,7 +467,7 @@ export class EvaluationClientWrapper { ): { error: Checked; wvc: undefined } | { wvc: WrappedVerifiableCredential; error: undefined } { // Decoded won't work for sd-jwt or jwt?!?! const [vcResult] = JsonPathUtils.extractInputField(wvp.decoded, [descriptor.path]) as Array<{ - value: string | IVerifiableCredential; + value: string | IVerifiablePresentation[] | IVerifiableCredential; }>; if (!vcResult) { @@ -474,16 +481,48 @@ export class EvaluationClientWrapper { }; } - // Find the wrapped VC based on the original VC - const originalVc = vcResult.value; - const wvc = wvp.vcs.find((wvc) => CredentialMapper.areOriginalVerifiableCredentialsEqual(wvc.original, originalVc)); + // FIXME figure out possible types, can't see that in debug mode... + const isCredential = CredentialMapper.isCredential(vcResult.value as OriginalVerifiableCredential); + if ( + !vcResult.value || + (typeof vcResult.value === 'string' && !isCredential) || + (typeof vcResult.value !== 'string' && !isCredential && !('verifiableCredential' in vcResult.value || 'vp' in vcResult.value)) + ) { + return { + error: { + status: Status.ERROR, + tag: 'NoVerifiableCredentials', + message: `No verifiable credentials found at path "${descriptor.path}" for submission.descriptor_path[${descriptorIndex}]`, + }, + wvc: undefined, + }; + } + + // When result is an array, extract the first Verifiable Credential from the array FIXME figure out proper types, can't see that in debug mode... + let originalVc; + if (isCredential) { + originalVc = vcResult.value; + } else if (typeof vcResult.value !== 'string') { + if ('verifiableCredential' in vcResult.value) { + originalVc = Array.isArray(vcResult.value.verifiableCredential) + ? vcResult.value.verifiableCredential[0] + : vcResult.value.verifiableCredential; + } else { + throw Error('Could not deduce original VC from evaluation result'); + } + } else { + throw Error('Could not deduce original VC from evaluation result'); + } + + // Find the corresponding Wrapped Verifiable Credential (wvc) based on the original VC + const wvc = wvp.vcs.find((wrappedVc) => CredentialMapper.areOriginalVerifiableCredentialsEqual(wrappedVc.original, originalVc)); if (!wvc) { return { error: { status: Status.ERROR, tag: 'SubmissionPathNotFound', - message: `Unable to find wrapped vc`, + message: `Unable to find wrapped VC for the extracted credential at path "${descriptor.path}" in descriptor_path[${descriptorIndex}]`, }, wvc: undefined, }; @@ -508,7 +547,7 @@ export class EvaluationClientWrapper { ): PresentationEvaluationResults { const result: PresentationEvaluationResults = { areRequiredCredentialsPresent: Status.INFO, - presentation: Array.isArray(wvps) ? wvps.map((wvp) => wvp.original) : wvps.original, + presentations: Array.isArray(wvps) ? wvps.map((wvp) => wvp.original) : [wvps.original], errors: [], warnings: [], value: submission, @@ -517,45 +556,67 @@ export class EvaluationClientWrapper { // If only a single VP is passed that is not w3c and no presentationSubmissionLocation, we set the default location to presentation. Otherwise we assume it's external const presentationSubmissionLocation = opts?.presentationSubmissionLocation ?? - (Array.isArray(wvps) || !CredentialMapper.isW3cPresentation(wvps.presentation) + (Array.isArray(wvps) || !CredentialMapper.isW3cPresentation(Array.isArray(wvps) ? wvps[0].presentation : wvps.presentation) ? PresentationSubmissionLocation.EXTERNAL : PresentationSubmissionLocation.PRESENTATION); - // We loop over all the descriptors in the submission - for (const descriptorIndex in submission.descriptor_map) { - const descriptor = submission.descriptor_map[descriptorIndex]; - - let vp: WrappedVerifiablePresentation; - let vc: WrappedVerifiableCredential; - let vcPath: string; + // Iterate over each descriptor in the submission + for (const [descriptorIndex, descriptor] of submission.descriptor_map.entries()) { + let matchingVps: WrappedVerifiablePresentation[] = []; if (presentationSubmissionLocation === PresentationSubmissionLocation.EXTERNAL) { - // Extract the VP from the wrapped VPs - const [vpResult] = JsonPathUtils.extractInputField(wvps, [descriptor.path]) as Array<{ value: WrappedVerifiablePresentation }>; - if (!vpResult) { + // Extract VPs matching the descriptor path + const vpResults = JsonPathUtils.extractInputField(wvps, [descriptor.path]) as Array<{ + value: WrappedVerifiablePresentation[]; + }>; + + if (!vpResults.length) { result.areRequiredCredentialsPresent = Status.ERROR; result.errors?.push({ status: Status.ERROR, tag: 'SubmissionPathNotFound', - message: `Unable to extract path ${descriptor.path} for submission.descriptor_path[${descriptorIndex}] from presentation(s)`, + message: `Unable to extract path ${descriptor.path} for submission.descriptor_map[${descriptorIndex}] from presentation(s)`, }); continue; } - vp = vpResult.value; - vcPath = `presentation ${descriptor.path}`; - if (vp.format !== descriptor.format) { + // Flatten the array of VPs + const allVps = vpResults.flatMap((vpResult) => vpResult.value); + + // Filter VPs that match the required format + matchingVps = allVps.filter((vp) => vp.format === descriptor.format); + + if (!matchingVps.length) { result.areRequiredCredentialsPresent = Status.ERROR; result.errors?.push({ status: Status.ERROR, tag: 'SubmissionFormatNoMatch', - message: `VP at path ${descriptor.path} has format ${vp.format}, while submission.descriptor_path[${descriptorIndex}] has format ${descriptor.format}`, + message: `No VP at path ${descriptor.path} matches the required format ${descriptor.format}`, }); continue; } + // Log a warning if multiple VPs match the descriptor + if (matchingVps.length > 1) { + result.warnings?.push({ + status: Status.WARN, + tag: 'MultipleVpsMatched', + message: `Multiple VPs matched for descriptor_path[${descriptorIndex}]. Using the first matching VP.`, + }); + } + } else { + // When submission location is PRESENTATION, assume a single VP + matchingVps = Array.isArray(wvps) ? [wvps[0]] : [wvps]; + } + + // Process the first matching VP + const vp = matchingVps[0]; + let vc: WrappedVerifiableCredential; + let vcPath: string = `presentation ${descriptor.path}`; + + if (presentationSubmissionLocation === PresentationSubmissionLocation.EXTERNAL) { if (descriptor.path_nested) { - const extractionResult = this.extractWrappedVcFromWrappedVp(descriptor.path_nested, descriptorIndex, vp); + const extractionResult = this.extractWrappedVcFromWrappedVp(descriptor.path_nested, descriptorIndex.toString(), vp); if (extractionResult.error) { result.areRequiredCredentialsPresent = Status.ERROR; result.errors?.push(extractionResult.error); @@ -565,6 +626,15 @@ export class EvaluationClientWrapper { vc = extractionResult.wvc; vcPath += ` with nested credential ${descriptor.path_nested.path}`; } else if (descriptor.format === 'vc+sd-jwt') { + if (!vp.vcs || !vp.vcs.length) { + result.areRequiredCredentialsPresent = Status.ERROR; + result.errors?.push({ + status: Status.ERROR, + tag: 'NoCredentialsFound', + message: `No credentials found in VP at path ${descriptor.path}`, + }); + continue; + } vc = vp.vcs[0]; } else { result.areRequiredCredentialsPresent = Status.ERROR; @@ -576,11 +646,7 @@ export class EvaluationClientWrapper { continue; } } else { - // TODO: check that not longer than 0 - vp = Array.isArray(wvps) ? wvps[0] : wvps; - vcPath = `credential ${descriptor.path}`; - - const extractionResult = this.extractWrappedVcFromWrappedVp(descriptor, descriptorIndex, vp); + const extractionResult = this.extractWrappedVcFromWrappedVp(descriptor, descriptorIndex.toString(), vp); if (extractionResult.error) { result.areRequiredCredentialsPresent = Status.ERROR; result.errors?.push(extractionResult.error); @@ -588,16 +654,20 @@ export class EvaluationClientWrapper { } vc = extractionResult.wvc; + vcPath = `credential ${descriptor.path}`; } // TODO: we should probably add support for holder dids in the kb-jwt of an SD-JWT. We can extract this from the // `wrappedPresentation.original.compactKbJwt`, but as HAIP doesn't use dids, we'll leave it for now. - const holderDIDs = CredentialMapper.isW3cPresentation(vp.presentation) && vp.presentation.holder ? [vp.presentation.holder] : []; - // Get the presentation definition only for this descriptor, so we can evaluate it separately + // Determine holder DIDs + const holderDIDs = + CredentialMapper.isW3cPresentation(vp.presentation) && vp.presentation.holder ? [vp.presentation.holder] : opts?.holderDIDs || []; + + // Get the presentation definition specific to the current descriptor const pdForDescriptor = this.internalPresentationDefinitionForDescriptor(pd, descriptor.id); - // Reset the client on each iteration. + // Reset and configure the evaluation client on each iteration this._client = new EvaluationClient(); this._client.evaluate(pdForDescriptor, [vc], { ...opts, @@ -606,6 +676,7 @@ export class EvaluationClientWrapper { generatePresentationSubmission: undefined, }); + // Check if the evaluation resulted in exactly one descriptor map entry if (this._client.presentationSubmission.descriptor_map.length !== 1) { const submissionDescriptor = `submission.descriptor_map[${descriptorIndex}]`; result.areRequiredCredentialsPresent = Status.ERROR; @@ -622,6 +693,7 @@ export class EvaluationClientWrapper { tag: 'SubmissionDoesNotSatisfyDefinition', // TODO: it would be nice to add the nested errors here for beter understanding WHY the submission // does not satisfy the definition, as we have that info, but we can only include one message here + message: submissionAgainstDefinitionResult.error, }); result.areRequiredCredentialsPresent = Status.ERROR; @@ -797,7 +869,10 @@ export class EvaluationClientWrapper { presentationSubmissionLocation?: PresentationSubmissionLocation; }, ): PresentationSubmission { - if (!this._client.results) { + if (!this._client.results || this._client.results.length === 0) { + if (vcs.length === 0) { + throw Error('The WrappedVerifiableCredentials input array is empty'); + } throw Error('You need to call evaluate() before pex.presentationFrom()'); } if (!this._client.generatePresentationSubmission) { diff --git a/lib/evaluation/handlers/limitDisclosureEvaluationHandler.ts b/lib/evaluation/handlers/limitDisclosureEvaluationHandler.ts index c49a5c7c..1945824d 100644 --- a/lib/evaluation/handlers/limitDisclosureEvaluationHandler.ts +++ b/lib/evaluation/handlers/limitDisclosureEvaluationHandler.ts @@ -17,7 +17,7 @@ import { applySdJwtLimitDisclosure, JsonPathUtils } from '../../utils'; import { EvaluationClient } from '../evaluationClient'; import { AbstractEvaluationHandler } from './abstractEvaluationHandler'; -import { elligibleInputDescriptorsForWrappedVc } from './markForSubmissionEvaluationHandler'; +import { eligibleInputDescriptorsForWrappedVc } from './markForSubmissionEvaluationHandler'; export class LimitDisclosureEvaluationHandler extends AbstractEvaluationHandler { constructor(client: EvaluationClient) { @@ -33,7 +33,7 @@ export class LimitDisclosureEvaluationHandler extends AbstractEvaluationHandler } private isLimitDisclosureSupported( - elligibleInputDescriptors: InputDescriptorWithIndex[], + eligibleInputDescriptors: InputDescriptorWithIndex[], wvc: WrappedVerifiableCredential, vcIndex: number, ): boolean { @@ -42,7 +42,7 @@ export class LimitDisclosureEvaluationHandler extends AbstractEvaluationHandler const limitDisclosureSignatures = this.client.limitDisclosureSignatureSuites; const decoded = wvc.decoded as IVerifiableCredential; const proofs = Array.isArray(decoded.proof) ? decoded.proof : decoded.proof ? [decoded.proof] : undefined; - const requiredLimitDisclosureInputDescriptorIds = elligibleInputDescriptors + const requiredLimitDisclosureInputDescriptorIds = eligibleInputDescriptors .map(({ inputDescriptor: { constraints }, inputDescriptorIndex }) => constraints?.limit_disclosure === Optionality.Required ? inputDescriptorIndex : undefined, ) @@ -52,7 +52,7 @@ export class LimitDisclosureEvaluationHandler extends AbstractEvaluationHandler // todo: Support/inspect array based proofs if (requiredLimitDisclosureInputDescriptorIds.length > 0) { this.createLimitDisclosureNotSupportedResult( - elligibleInputDescriptors.map((i) => i.inputDescriptorIndex), + eligibleInputDescriptors.map((i) => i.inputDescriptorIndex), vcIndex, 'Multiple proofs on verifiable credential not supported for limit disclosure', ); @@ -78,27 +78,23 @@ export class LimitDisclosureEvaluationHandler extends AbstractEvaluationHandler private evaluateLimitDisclosure(inputDescriptors: Array, wrappedVcs: WrappedVerifiableCredential[]): void { wrappedVcs.forEach((wvc, vcIndex) => { - const elligibleInputDescriptors = elligibleInputDescriptorsForWrappedVc(inputDescriptors, vcIndex, this.getResults()); - const includeLimitDisclosure = elligibleInputDescriptors.some( + const eligibleInputDescriptors = eligibleInputDescriptorsForWrappedVc(inputDescriptors, vcIndex, this.getResults()); + const includeLimitDisclosure = eligibleInputDescriptors.some( ({ inputDescriptor: { constraints } }) => constraints?.limit_disclosure === Optionality.Preferred || constraints?.limit_disclosure === Optionality.Required, ); - if ( - elligibleInputDescriptors.length > 0 && - includeLimitDisclosure && - this.isLimitDisclosureSupported(elligibleInputDescriptors, wvc, vcIndex) - ) { - this.enforceLimitDisclosure(wrappedVcs, elligibleInputDescriptors, vcIndex); + if (eligibleInputDescriptors.length > 0 && includeLimitDisclosure && this.isLimitDisclosureSupported(eligibleInputDescriptors, wvc, vcIndex)) { + this.enforceLimitDisclosure(wrappedVcs, eligibleInputDescriptors, vcIndex); } }); } - private enforceLimitDisclosure(wrappedVcs: WrappedVerifiableCredential[], elligibleInputDescriptors: InputDescriptorWithIndex[], vcIndex: number) { + private enforceLimitDisclosure(wrappedVcs: WrappedVerifiableCredential[], eligibleInputDescriptors: InputDescriptorWithIndex[], vcIndex: number) { const wvc = wrappedVcs[vcIndex]; if (CredentialMapper.isWrappedSdJwtVerifiableCredential(wvc)) { - const presentationFrame = this.createSdJwtPresentationFrame(elligibleInputDescriptors, wvc.credential, vcIndex); + const presentationFrame = this.createSdJwtPresentationFrame(eligibleInputDescriptors, wvc.credential, vcIndex); // We update the SD-JWT to it's presentation format (remove disclosures, update pretty payload, etc..), except // we don't create or include the (optional) KB-JWT yet, this is done when we create the presentation @@ -109,18 +105,18 @@ export class LimitDisclosureEvaluationHandler extends AbstractEvaluationHandler // But we also want to keep the format of the original credential. wvc.original = CredentialMapper.isSdJwtDecodedCredential(wvc.original) ? wvc.credential : wvc.credential.compactSdJwtVc; - for (const { inputDescriptorIndex, inputDescriptor } of elligibleInputDescriptors) { + for (const { inputDescriptorIndex, inputDescriptor } of eligibleInputDescriptors) { this.createSuccessResult(inputDescriptorIndex, `$[${vcIndex}]`, inputDescriptor.constraints?.limit_disclosure); } } } else if (CredentialMapper.isW3cCredential(wvc.credential)) { - const internalCredentialToSend = this.createVcWithRequiredFields(elligibleInputDescriptors, wvc.credential, vcIndex); + const internalCredentialToSend = this.createVcWithRequiredFields(eligibleInputDescriptors, wvc.credential, vcIndex); /* When verifiableCredentialToSend is null/undefined an error is raised, the credential will * remain untouched and the verifiable credential won't be submitted. */ if (internalCredentialToSend) { wvc.credential = internalCredentialToSend; - for (const { inputDescriptorIndex, inputDescriptor } of elligibleInputDescriptors) { + for (const { inputDescriptorIndex, inputDescriptor } of eligibleInputDescriptors) { this.createSuccessResult(inputDescriptorIndex, `$[${vcIndex}]`, inputDescriptor.constraints?.limit_disclosure); } } diff --git a/lib/evaluation/handlers/markForSubmissionEvaluationHandler.ts b/lib/evaluation/handlers/markForSubmissionEvaluationHandler.ts index f9e422ac..412b4fbe 100644 --- a/lib/evaluation/handlers/markForSubmissionEvaluationHandler.ts +++ b/lib/evaluation/handlers/markForSubmissionEvaluationHandler.ts @@ -10,7 +10,7 @@ import { EvaluationClient } from '../evaluationClient'; import { AbstractEvaluationHandler } from './abstractEvaluationHandler'; -export function elligibleInputDescriptorsForWrappedVc( +export function eligibleInputDescriptorsForWrappedVc( inputDescriptors: Array, vcIndex: number, results: HandlerCheckResult[], diff --git a/lib/evaluation/handlers/uriEvaluationHandler.ts b/lib/evaluation/handlers/uriEvaluationHandler.ts index f4c07f88..c42dcaa3 100644 --- a/lib/evaluation/handlers/uriEvaluationHandler.ts +++ b/lib/evaluation/handlers/uriEvaluationHandler.ts @@ -19,8 +19,6 @@ import { EvaluationClient } from '../evaluationClient'; import { AbstractEvaluationHandler } from './abstractEvaluationHandler'; export class UriEvaluationHandler extends AbstractEvaluationHandler { - static matchAll = require('string.prototype.matchall'); - constructor(client: EvaluationClient) { super(client); } @@ -220,8 +218,8 @@ export class UriEvaluationHandler extends AbstractEvaluationHandler { private static containsHashlink(url: string): boolean { return !( - this.matchAll(url, UriEvaluationHandler.HASHLINK_QUERY_URL_REGEX).next().done && - this.matchAll(url, UriEvaluationHandler.HASHLINK_URL_ENCODED_REGEX).next().done + url.matchAll(UriEvaluationHandler.HASHLINK_QUERY_URL_REGEX).next().done && + url.matchAll(UriEvaluationHandler.HASHLINK_URL_ENCODED_REGEX).next().done ); } } diff --git a/lib/signing/types.ts b/lib/signing/types.ts index 2961df82..e46c4c6b 100644 --- a/lib/signing/types.ts +++ b/lib/signing/types.ts @@ -7,10 +7,10 @@ import { IProofType, OriginalVerifiableCredential, SdJwtDecodedVerifiableCredential, + SdJwtVcKbJwtHeader, SdJwtVcKbJwtPayload, W3CVerifiablePresentation, } from '@sphereon/ssi-types'; -import { SdJwtVcKbJwtHeader } from '@sphereon/ssi-types/src/types/sd-jwt-vc'; import { PresentationEvaluationResults } from '../evaluation'; @@ -100,7 +100,7 @@ export interface PresentationResult { /** * The resulting presentation, can have an embedded submission data depending on the location parameter */ - presentation: IPresentation | SdJwtDecodedVerifiableCredential | PartialSdJwtDecodedVerifiableCredential; + presentations: Array; /** * The resulting location of the presentation submission. @@ -122,7 +122,7 @@ export interface VerifiablePresentationResult { /** * The resulting VP, can have an embedded submission data depending on the location parameter */ - verifiablePresentation: W3CVerifiablePresentation | CompactSdJwtVc; + verifiablePresentations: Array; /** * The resulting location of the presentation submission. diff --git a/lib/utils/jsonPathUtils.ts b/lib/utils/jsonPathUtils.ts index 18296c71..bcd2f19e 100644 --- a/lib/utils/jsonPathUtils.ts +++ b/lib/utils/jsonPathUtils.ts @@ -4,7 +4,6 @@ import { PresentationDefinitionV1, PresentationDefinitionV2 } from '@sphereon/pe import { InputFieldType, IPresentationDefinition, PathComponent } from '../types'; export class JsonPathUtils { - static matchAll = require('string.prototype.matchall'); static REGEX_PATH = /@\w+/g; /** * @param obj: any object can be found in verifiablePresentation.verifiableCredential[i] @@ -121,7 +120,7 @@ export class JsonPathUtils { } private static modifyPathWithSpecialCharacter(path: string): string { - const matches = this.matchAll(path, this.REGEX_PATH); + const matches = path.matchAll(JsonPathUtils.REGEX_PATH); path = this.modifyPathRecursive(matches, path); return path; } @@ -139,7 +138,7 @@ export class JsonPathUtils { if (path.substring(atIdx - 2, atIdx) === '..') { path = path.substring(0, atIdx - 2) + "..['" + next.value[0] + "']" + path.substring(atIdx + next.value[0].length); indexChanged = true; - const matches = this.matchAll(path, this.REGEX_PATH); + const matches = path.matchAll(JsonPathUtils.REGEX_PATH); this.modifyPathRecursive(matches, path); } else if (path.charAt(atIdx - 1) === '.') { path = path.substring(0, atIdx - 1) + "['" + next.value[0] + "']" + path.substring(atIdx + next.value[0].length); diff --git a/package.json b/package.json index dd0a31de..8aa442f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sphereon/pex", - "version": "5.0.0-unstable.0", + "version": "5.0.0-unstable.18", "description": "A Typescript implementation of the v1 and v2 DIF Presentation Exchange specification", "main": "dist/main/index.js", "module": "dist/module/index.js", @@ -35,33 +35,32 @@ "test": "run-s test:*", "test:lint": "eslint . --ext .ts", "test:prettier": "prettier \"{lib,test}/**/*.ts\" --list-different", - "test:unit": "jest", - "test:cov": "jest --ci --coverage && codecov" + "test:cov": "jest --ci --coverage", + "test:unit": "jest" }, "engines": { "node": ">=18" }, "dependencies": { "@astronautlabs/jsonpath": "^1.1.2", - "@sd-jwt/decode": "^0.6.1", - "@sd-jwt/present": "^0.6.1", - "@sd-jwt/types": "^0.6.1", + "@sd-jwt/decode": "^0.7.2", + "@sd-jwt/present": "^0.7.2", + "@sd-jwt/types": "^0.7.2", "@sphereon/pex-models": "^2.3.1", - "@sphereon/ssi-types": "0.29.1-unstable.121", + "@sphereon/ssi-types": "0.30.1", "ajv": "^8.12.0", "ajv-formats": "^2.1.1", "jwt-decode": "^3.1.2", "uint8arrays": "^3.1.1", - "nanoid": "^3.3.7", - "string.prototype.matchall": "^4.0.10" + "nanoid": "^3.3.7" }, "devDependencies": { "@types/jest": "^29.5.12", "@types/node": "^18.19.26", "@typescript-eslint/eslint-plugin": "^7.3.1", "@typescript-eslint/parser": "^7.3.1", + "@sd-jwt/core": "^0.7.2", "ajv-cli": "^5.0.0", - "codecov": "^3.8.3", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-eslint-comments": "^3.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 632b5529..32d774c0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,20 +9,20 @@ dependencies: specifier: ^1.1.2 version: 1.1.2 '@sd-jwt/decode': - specifier: ^0.6.1 - version: 0.6.1 + specifier: ^0.7.2 + version: 0.7.2 '@sd-jwt/present': - specifier: ^0.6.1 - version: 0.6.1 + specifier: ^0.7.2 + version: 0.7.2 '@sd-jwt/types': - specifier: ^0.6.1 - version: 0.6.1 + specifier: ^0.7.2 + version: 0.7.2 '@sphereon/pex-models': specifier: ^2.3.1 version: 2.3.1 '@sphereon/ssi-types': - specifier: 0.29.1-unstable.121 - version: 0.29.1-unstable.121(ts-node@10.9.2) + specifier: 0.30.1 + version: 0.30.1(ts-node@10.9.2) ajv: specifier: ^8.12.0 version: 8.12.0 @@ -35,14 +35,14 @@ dependencies: nanoid: specifier: ^3.3.7 version: 3.3.7 - string.prototype.matchall: - specifier: ^4.0.10 - version: 4.0.10 uint8arrays: specifier: ^3.1.1 version: 3.1.1 devDependencies: + '@sd-jwt/core': + specifier: ^0.7.2 + version: 0.7.2 '@types/jest': specifier: ^29.5.12 version: 29.5.12 @@ -58,9 +58,6 @@ devDependencies: ajv-cli: specifier: ^5.0.0 version: 5.0.0(ts-node@10.9.2) - codecov: - specifier: ^3.8.3 - version: 3.8.3 eslint: specifier: ^8.57.0 version: 8.57.0 @@ -953,6 +950,16 @@ packages: resolution: {integrity: sha512-6CyAclxj3Nb0XT7GHK6K4zK6k2xJm6E4Ft0Ohjt4WgegiFUHEtFb2CGzmPmGBwoIhrLsqNLYfLr04Y1GePrzZg==} dev: false + /@sd-jwt/core@0.7.2: + resolution: {integrity: sha512-vix1GplUFc1A9H42r/yXkg7cKYthggyqZEwlFdsBbn4xdZNE+AHVF4N7kPa1pPxipwN3UIHd4XnQ5MJV15mhsQ==} + engines: {node: '>=18'} + dependencies: + '@sd-jwt/decode': 0.7.2 + '@sd-jwt/present': 0.7.2 + '@sd-jwt/types': 0.7.2 + '@sd-jwt/utils': 0.7.2 + dev: true + /@sd-jwt/decode@0.6.1: resolution: {integrity: sha512-QgTIoYd5zyKKLgXB4xEYJTrvumVwtsj5Dog0v0L9UH9ZvHekDaeexS247X7A4iSdzTvmZzUpGskgABOa4D8NmQ==} engines: {node: '>=16'} @@ -961,20 +968,30 @@ packages: '@sd-jwt/utils': 0.6.1 dev: false - /@sd-jwt/present@0.6.1: - resolution: {integrity: sha512-QRD3TUDLj4PqQNZ70bBxh8FLLrOE9mY8V9qiZrJSsaDOLFs2p1CtZG+v9ig62fxFYJZMf4bWKwYjz+qqGAtxCg==} - engines: {node: '>=16'} + /@sd-jwt/decode@0.7.2: + resolution: {integrity: sha512-dan2LSvK63SKwb62031G4r7TE4TaiI0EK1KbPXqS+LCXNkNDUHqhtYp9uOpj+grXceCsMtMa2f8VnUfsjmwHHg==} + engines: {node: '>=18'} dependencies: - '@sd-jwt/decode': 0.6.1 - '@sd-jwt/types': 0.6.1 - '@sd-jwt/utils': 0.6.1 - dev: false + '@sd-jwt/types': 0.7.2 + '@sd-jwt/utils': 0.7.2 + + /@sd-jwt/present@0.7.2: + resolution: {integrity: sha512-mQV85u2+mLLy2VZ9Wx2zpaB6yTDnbhCfWkP7eeCrzJQHBKAAHko8GrylEFmLKewFIcajS/r4lT/zHOsCkp5pZw==} + engines: {node: '>=18'} + dependencies: + '@sd-jwt/decode': 0.7.2 + '@sd-jwt/types': 0.7.2 + '@sd-jwt/utils': 0.7.2 /@sd-jwt/types@0.6.1: resolution: {integrity: sha512-LKpABZJGT77jNhOLvAHIkNNmGqXzyfwBT+6r+DN9zNzMx1CzuNR0qXk1GMUbast9iCfPkGbnEpUv/jHTBvlIvg==} engines: {node: '>=16'} dev: false + /@sd-jwt/types@0.7.2: + resolution: {integrity: sha512-1NRKowiW0ZiB9SGLApLPBH4Xk8gDQJ+nA9NdZ+uy6MmJKLEwjuJxO7yTvRIv/jX/0/Ebh339S7Kq4RD2AiFuRg==} + engines: {node: '>=18'} + /@sd-jwt/utils@0.6.1: resolution: {integrity: sha512-1NHZ//+GecGQJb+gSdDicnrHG0DvACUk9jTnXA5yLZhlRjgkjyfJLNsCZesYeCyVp/SiyvIC9B+JwoY4kI0TwQ==} engines: {node: '>=16'} @@ -983,6 +1000,13 @@ packages: js-base64: 3.7.7 dev: false + /@sd-jwt/utils@0.7.2: + resolution: {integrity: sha512-aMPY7uHRMgyI5PlDvEiIc+eBFGC1EM8OCQRiEjJ8HGN0pajWMYj0qwSw7pS90A49/DsYU1a5Zpvb7nyjgGH0Yg==} + engines: {node: '>=18'} + dependencies: + '@sd-jwt/types': 0.7.2 + js-base64: 3.7.7 + /@sinclair/typebox@0.27.8: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true @@ -1015,19 +1039,20 @@ packages: '@js-joda/timezone': 2.3.0(@js-joda/core@5.6.3) format-util: 1.0.5 dev: false + bundledDependencies: [] /@sphereon/pex-models@2.3.1: resolution: {integrity: sha512-SByU4cJ0XYA6VZQ/L6lsSiRcFtBPHbFioCeQ4GP7/W/jQ+PSBD7uK2oTnKQ9/0iEiMK/6JYqhKgLs4a9UX3UTQ==} dev: false - /@sphereon/ssi-sdk-ext.did-utils@0.24.1-next.112(ts-node@10.9.2): - resolution: {integrity: sha512-/qwAk5ivJBF8uRgsA66RK1nBYpDLvoE7ma05HHxENHfQFvrtoE29m/gjcyIFxvlew+HQhI3OHwzOZXGeadLGGw==} + /@sphereon/ssi-sdk-ext.did-utils@0.24.1-unstable.130(ts-node@10.9.2): + resolution: {integrity: sha512-I+0VjitRjisABWm8RtTPQG57tFwfUS13Wud30OvBoADRxnaA0guUrkS82AYtV6YD0TBHdrd0D6a0RCJwK9SvDg==} dependencies: '@ethersproject/networks': 5.7.1 '@ethersproject/transactions': 5.7.0 '@sphereon/did-uni-client': 0.6.3 - '@sphereon/ssi-sdk-ext.key-utils': 0.24.1-next.112 - '@sphereon/ssi-sdk-ext.x509-utils': 0.24.1-next.112 + '@sphereon/ssi-sdk-ext.key-utils': 0.24.1-unstable.130 + '@sphereon/ssi-sdk-ext.x509-utils': 0.24.1-unstable.130 '@sphereon/ssi-sdk.agent-config': 0.29.1-unstable.161(ts-node@10.9.2) '@sphereon/ssi-sdk.core': 0.29.1-unstable.161 '@sphereon/ssi-types': 0.29.1-unstable.161 @@ -1060,52 +1085,12 @@ packages: - typeorm-aurora-data-api-driver dev: false - /@sphereon/ssi-sdk-ext.did-utils@0.24.1-unstable.112(ts-node@10.9.2): - resolution: {integrity: sha512-nc0jFPOWg0H20S8m83aQUpNym0Wx0rJCGkgpH6GdK8gBtgza8Y9DvAap1AYZug18WbqPcF6rBjvtIJqAKsSvlQ==} + /@sphereon/ssi-sdk-ext.identifier-resolution@0.24.1-unstable.130(ts-node@10.9.2): + resolution: {integrity: sha512-9mY+qgXmbZCC8aic99R7B3vKBHBakDiC6Sktgd7Q9AknR8cCmvdrmTgnOETrLng9L43uNOJnNTMG/4T6LqmtsA==} dependencies: - '@ethersproject/networks': 5.7.1 - '@ethersproject/transactions': 5.7.0 - '@sphereon/did-uni-client': 0.6.3 - '@sphereon/ssi-sdk-ext.key-utils': 0.24.1-unstable.112 - '@sphereon/ssi-sdk-ext.x509-utils': 0.24.1-unstable.112 - '@sphereon/ssi-sdk.agent-config': 0.29.1-unstable.161(ts-node@10.9.2) - '@sphereon/ssi-sdk.core': 0.29.1-unstable.161 - '@sphereon/ssi-types': 0.29.1-unstable.161 - '@stablelib/ed25519': 1.0.3 - '@veramo/core': 4.2.0 - '@veramo/utils': 4.2.0 - did-jwt: 6.11.6 - did-resolver: 4.1.0 - elliptic: 6.5.7 - uint8arrays: 3.1.1 - transitivePeerDependencies: - - '@google-cloud/spanner' - - '@sap/hana-client' - - better-sqlite3 - - encoding - - hdb-pool - - ioredis - - mongodb - - mssql - - mysql2 - - oracledb - - pg - - pg-native - - pg-query-stream - - redis - - sql.js - - sqlite3 - - supports-color - - ts-node - - typeorm-aurora-data-api-driver - dev: false - - /@sphereon/ssi-sdk-ext.identifier-resolution@0.24.1-unstable.112(ts-node@10.9.2): - resolution: {integrity: sha512-VBkJjHokFNsQ0wsHUbyCysMuShTOEuK6yrvyW64uOFcB2hzq1J/wi9CewI+YRHv7mnejBlu46uYNycvOKKRcsQ==} - dependencies: - '@sphereon/ssi-sdk-ext.did-utils': 0.24.1-unstable.112(ts-node@10.9.2) - '@sphereon/ssi-sdk-ext.key-utils': 0.24.1-unstable.112 - '@sphereon/ssi-sdk-ext.x509-utils': 0.24.1-unstable.112 + '@sphereon/ssi-sdk-ext.did-utils': 0.24.1-unstable.130(ts-node@10.9.2) + '@sphereon/ssi-sdk-ext.key-utils': 0.24.1-unstable.130 + '@sphereon/ssi-sdk-ext.x509-utils': 0.24.1-unstable.130 '@sphereon/ssi-sdk.agent-config': 0.29.1-unstable.161(ts-node@10.9.2) '@sphereon/ssi-types': 0.29.1-unstable.161 '@veramo/core': 4.2.0 @@ -1135,16 +1120,16 @@ packages: - typeorm-aurora-data-api-driver dev: false - /@sphereon/ssi-sdk-ext.jwt-service@0.24.1-unstable.112(ts-node@10.9.2): - resolution: {integrity: sha512-OrBaSg5wLSehkJ4MyuyDWKD4CRIBERnJqRT0o/y5DbaCF3k02+/lN/rWP+4qwk2w192fIEAExG4L2GwZM/5PLQ==} + /@sphereon/ssi-sdk-ext.jwt-service@0.24.1-unstable.130(ts-node@10.9.2): + resolution: {integrity: sha512-MHLGRmJODEYJyFoXKwlKMYzf48vS5JcUkGk0W4sqmrY1wwcw+ro3l8adIprG37mNuknXBs9Mv0x/tvibE9wwCQ==} dependencies: - '@sphereon/ssi-sdk-ext.did-utils': 0.24.1-next.112(ts-node@10.9.2) - '@sphereon/ssi-sdk-ext.identifier-resolution': 0.24.1-unstable.112(ts-node@10.9.2) - '@sphereon/ssi-sdk-ext.key-manager': 0.24.1-unstable.112 - '@sphereon/ssi-sdk-ext.key-utils': 0.24.1-next.112 - '@sphereon/ssi-sdk-ext.x509-utils': 0.24.1-unstable.112 + '@sphereon/ssi-sdk-ext.did-utils': 0.24.1-unstable.130(ts-node@10.9.2) + '@sphereon/ssi-sdk-ext.identifier-resolution': 0.24.1-unstable.130(ts-node@10.9.2) + '@sphereon/ssi-sdk-ext.key-manager': 0.24.1-unstable.130 + '@sphereon/ssi-sdk-ext.key-utils': 0.24.1-unstable.130 + '@sphereon/ssi-sdk-ext.x509-utils': 0.24.1-unstable.130 '@sphereon/ssi-sdk.agent-config': 0.29.1-unstable.161(ts-node@10.9.2) - '@sphereon/ssi-types': 0.29.1-unstable.237 + '@sphereon/ssi-types': 0.29.1-unstable.161 '@veramo/core': 4.2.0 '@veramo/utils': 4.2.0 debug: 4.3.6 @@ -1172,8 +1157,8 @@ packages: - typeorm-aurora-data-api-driver dev: false - /@sphereon/ssi-sdk-ext.key-manager@0.24.1-unstable.112: - resolution: {integrity: sha512-XdXV4qj+BYTZWyGHduWQxl0mxCYt5CF0Q93p4Thbm2/hjfaAC6aJi2WAXFGTIri95QVbKW1Uscob0CjNCVkWdg==} + /@sphereon/ssi-sdk-ext.key-manager@0.24.1-unstable.130: + resolution: {integrity: sha512-O/6NlKmlYRnEyP/mAI2Diu0qptMSqZfVwqog8KAOG/G8JUmktfSQmclBW8RoJ6AD9uY65BGzNk1oAVuuMv4Dog==} dependencies: '@veramo/core': 4.2.0 '@veramo/key-manager': 4.2.0 @@ -1182,35 +1167,11 @@ packages: - supports-color dev: false - /@sphereon/ssi-sdk-ext.key-utils@0.24.1-next.112: - resolution: {integrity: sha512-pySpFqfKn4fJ1wJMWRiVMh6zDyEQFs7adkyxlO5uDTKEYJ/9hQ++MD2t+seDpYjq5x2Wh+g60OzD1uiVdbL2aA==} - dependencies: - '@ethersproject/random': 5.7.0 - '@sphereon/ssi-sdk-ext.x509-utils': 0.24.1-next.112 - '@sphereon/ssi-types': 0.29.1-unstable.161 - '@stablelib/ed25519': 1.0.3 - '@stablelib/sha256': 1.0.1 - '@stablelib/sha512': 1.0.1 - '@trust/keyto': 1.0.1 - '@veramo/core': 4.2.0 - base64url: 3.0.1 - debug: 4.3.6 - did-resolver: 4.1.0 - elliptic: 6.5.7 - lodash.isplainobject: 4.0.6 - multiformats: 9.9.0 - uint8arrays: 3.1.1 - varint: 6.0.0 - web-encoding: 1.1.5 - transitivePeerDependencies: - - supports-color - dev: false - - /@sphereon/ssi-sdk-ext.key-utils@0.24.1-unstable.112: - resolution: {integrity: sha512-er6TwGUWxlao2lSP97r1DTFlUXcPSMsIToULOWQJp6wKbvCuvV6pN5luS0qKB/W0/TOUE5kXzFwNx086BPnPRA==} + /@sphereon/ssi-sdk-ext.key-utils@0.24.1-unstable.130: + resolution: {integrity: sha512-DCyXW18g1OAuZ+aFHzQGrbZSx793DX94LSFnrWlOTMnYeILmrizuFksUlWSb3lTqQGAqWBC48NoR3I1H6lSMEQ==} dependencies: '@ethersproject/random': 5.7.0 - '@sphereon/ssi-sdk-ext.x509-utils': 0.24.1-unstable.112 + '@sphereon/ssi-sdk-ext.x509-utils': 0.24.1-unstable.130 '@sphereon/ssi-types': 0.29.1-unstable.161 '@stablelib/ed25519': 1.0.3 '@stablelib/sha256': 1.0.1 @@ -1230,20 +1191,8 @@ packages: - supports-color dev: false - /@sphereon/ssi-sdk-ext.x509-utils@0.24.1-next.112: - resolution: {integrity: sha512-D15Kqh1oH620dMuPkImfNmVOpXtperQm6dGbo3jiJ9lvafjJzuVM9nHIeDoSI/uh/LkUXB7xuqD+4sATE/RO9g==} - dependencies: - '@trust/keyto': 1.0.1 - debug: 4.3.6 - js-x509-utils: 1.0.7 - pkijs: 3.2.4 - uint8arrays: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: false - - /@sphereon/ssi-sdk-ext.x509-utils@0.24.1-unstable.112: - resolution: {integrity: sha512-bbx2jFoqWhW/xYABVwg3HiUo15yztPt3s+9bJtdB8n4PCjin4Nq3+vFvaHsmu70yAGkbWfsBcBVW6Y3oFtvpAA==} + /@sphereon/ssi-sdk-ext.x509-utils@0.24.1-unstable.130: + resolution: {integrity: sha512-JDX8i0WrwONaOivZXB+OxJQGkln7vuSLS61tOYl7M1RyPGixdBYuEuACsdvWf6egYOpaWmhmXZzaAOj18eDddw==} dependencies: '@trust/keyto': 1.0.1 debug: 4.3.6 @@ -1298,12 +1247,23 @@ packages: - supports-color dev: false - /@sphereon/ssi-types@0.29.1-unstable.121(ts-node@10.9.2): - resolution: {integrity: sha512-g5qt2cRa/9t3WrBWMneGOrwjyU2Mqdh4LlKeO6japli5bgl5D6lim91F++m1iIIhOYP4dqPpk5PLjy9XQlLyEw==} + /@sphereon/ssi-types@0.29.1-unstable.161: + resolution: {integrity: sha512-ifMADjk6k0f97/isK/4Qw/PX6n4k+qS5k6mmmH47MTD3KMDddVghoXycsvNw7wObJdLUalHBX630ghr+u21oMg==} dependencies: '@sd-jwt/decode': 0.6.1 + debug: 4.3.6 + events: 3.3.0 + jwt-decode: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /@sphereon/ssi-types@0.30.1(ts-node@10.9.2): + resolution: {integrity: sha512-vbYaxQXb71sOPwDj7TRDlUGfIHKVVs8PiHfImPBgSBshrD7VpEHOrB+EwwavMm5MAQvWK/yblGmzk7FHds7SHA==} + dependencies: + '@sd-jwt/decode': 0.7.2 '@sphereon/kmp-mdl-mdoc': 0.2.0-SNAPSHOT.22 - '@sphereon/ssi-sdk-ext.jwt-service': 0.24.1-unstable.112(ts-node@10.9.2) + '@sphereon/ssi-sdk-ext.jwt-service': 0.24.1-unstable.130(ts-node@10.9.2) debug: 4.3.6 events: 3.3.0 jwt-decode: 3.1.2 @@ -1329,29 +1289,6 @@ packages: - typeorm-aurora-data-api-driver dev: false - /@sphereon/ssi-types@0.29.1-unstable.161: - resolution: {integrity: sha512-ifMADjk6k0f97/isK/4Qw/PX6n4k+qS5k6mmmH47MTD3KMDddVghoXycsvNw7wObJdLUalHBX630ghr+u21oMg==} - dependencies: - '@sd-jwt/decode': 0.6.1 - debug: 4.3.6 - events: 3.3.0 - jwt-decode: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: false - - /@sphereon/ssi-types@0.29.1-unstable.237: - resolution: {integrity: sha512-H9vqaFbCwbZpPUk5x84Cn1GeIFvwi7EZAsLN4h6EkXDwm55yOT76dvcSVUnL6obC2AzGr+Bjyv4R2cZSwKkguw==} - dependencies: - '@sd-jwt/decode': 0.6.1 - '@sphereon/kmp-mdl-mdoc': 0.2.0-SNAPSHOT.22 - debug: 4.3.6 - events: 3.3.0 - jwt-decode: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: false - /@sqltools/formatter@1.2.5: resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==} dev: false @@ -1478,11 +1415,6 @@ packages: resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} dev: true - /@tootallnate/once@1.1.2: - resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} - engines: {node: '>= 6'} - dev: true - /@trust/keyto@1.0.1: resolution: {integrity: sha512-OXTmKkrnkwktCX86XA7eWs1TQ6u64enm0syzAfNhjigbuGLy5aLhbhRYWtjt4zzdG/irWudluheRZ9Ic9pCwsA==} dependencies: @@ -1766,7 +1698,7 @@ packages: cross-fetch: 3.1.8 debug: 4.3.6 did-jwt: 6.11.6 - did-jwt-vc: 3.2.15 + did-jwt-vc: 3.1.3 did-resolver: 4.1.0 elliptic: 6.5.7 multiformats: 9.7.1 @@ -1799,15 +1731,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - dependencies: - debug: 4.3.6 - transitivePeerDependencies: - - supports-color - dev: true - /ajv-cli@5.0.0(ts-node@10.9.2): resolution: {integrity: sha512-LY4m6dUv44HTyhV+u2z5uX4EhPYTM38Iv1jdgDJJJCyOOuqB8KtZEGjPZ2T+sh5ZIJrXUfgErYx/j3gLd3+PlQ==} hasBin: true @@ -1922,18 +1845,13 @@ packages: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true - /argv@0.0.2: - resolution: {integrity: sha512-dEamhpPEwRUBpLNHeuCm/v+g0anFByHahxodVO/BbAarHVBBg2MccCwf9K+o1Pof+2btdnkJelYVUWjW/VrATw==} - engines: {node: '>=0.6.10'} - deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. - dev: true - /array-buffer-byte-length@1.0.1: resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.7 is-array-buffer: 3.0.4 + dev: true /array-includes@3.1.7: resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} @@ -1995,6 +1913,7 @@ packages: get-intrinsic: 1.2.4 is-array-buffer: 3.0.4 is-shared-array-buffer: 1.0.3 + dev: true /asn1.js-rfc5280@3.0.0: resolution: {integrity: sha512-Y2LZPOWeZ6qehv698ZgOGGCZXBQShObWnGthTrIFlIQjuV1gg2B8QOhWFRExq/MR1VnPpIIe7P9vX2vElxv+Pg==} @@ -2297,22 +2216,6 @@ packages: engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} dev: true - /codecov@3.8.3: - resolution: {integrity: sha512-Y8Hw+V3HgR7V71xWH2vQ9lyS358CbGCldWlJFR0JirqoGtOoas3R3/OclRTvgUYFK29mmJICDPauVKmpqbwhOA==} - engines: {node: '>=4.0'} - deprecated: https://about.codecov.io/blog/codecov-uploader-deprecation-plan/ - hasBin: true - dependencies: - argv: 0.0.2 - ignore-walk: 3.0.4 - js-yaml: 3.14.1 - teeny-request: 7.1.1 - urlgrey: 1.0.0 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - /collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} dev: true @@ -2430,6 +2333,7 @@ packages: call-bind: 1.0.7 es-errors: 1.3.0 is-data-view: 1.0.1 + dev: true /data-view-byte-length@1.0.1: resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} @@ -2438,6 +2342,7 @@ packages: call-bind: 1.0.7 es-errors: 1.3.0 is-data-view: 1.0.1 + dev: true /data-view-byte-offset@1.0.0: resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} @@ -2446,6 +2351,7 @@ packages: call-bind: 1.0.7 es-errors: 1.3.0 is-data-view: 1.0.1 + dev: true /dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} @@ -2535,6 +2441,7 @@ packages: define-data-property: 1.1.4 has-property-descriptors: 1.0.2 object-keys: 1.1.1 + dev: true /des.js@1.1.0: resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} @@ -2548,6 +2455,14 @@ packages: engines: {node: '>=8'} dev: true + /did-jwt-vc@3.1.3: + resolution: {integrity: sha512-qB1FiQ0sT/FUR5+mQ//P5lS0Gllrtes2OxC3WVMOt8ND0LolF92ohozv50ukyOvB2zBzgfm5durcIPqQcoI+LA==} + engines: {node: '>=14'} + dependencies: + did-jwt: 6.11.6 + did-resolver: 4.1.0 + dev: false + /did-jwt-vc@3.2.15: resolution: {integrity: sha512-M/WPiL34CQUiN4bvWnZ0OFHJ3usPtstfQfbNbHAWHvwjeCGi7nAdv62VXHgy2xIhJMc790hH7PsMN3i6SCGEyg==} engines: {node: '>=18'} @@ -2719,6 +2634,7 @@ packages: typed-array-length: 1.0.5 unbox-primitive: 1.0.2 which-typed-array: 1.1.15 + dev: true /es-abstract@1.23.2: resolution: {integrity: sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==} @@ -2770,6 +2686,7 @@ packages: typed-array-length: 1.0.5 unbox-primitive: 1.0.2 which-typed-array: 1.1.15 + dev: true /es-define-property@1.0.0: resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} @@ -2786,6 +2703,7 @@ packages: engines: {node: '>= 0.4'} dependencies: es-errors: 1.3.0 + dev: true /es-set-tostringtag@2.0.3: resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} @@ -2794,6 +2712,7 @@ packages: get-intrinsic: 1.2.4 has-tostringtag: 1.0.2 hasown: 2.0.2 + dev: true /es-shim-unscopables@1.0.2: resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} @@ -2808,6 +2727,7 @@ packages: is-callable: 1.2.7 is-date-object: 1.0.5 is-symbol: 1.0.4 + dev: true /escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} @@ -3105,12 +3025,6 @@ packages: /fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - /fast-url-parser@1.1.3: - resolution: {integrity: sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==} - dependencies: - punycode: 1.4.1 - dev: true - /fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} dependencies: @@ -3214,9 +3128,11 @@ packages: define-properties: 1.2.1 es-abstract: 1.22.5 functions-have-names: 1.2.3 + dev: true /functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} @@ -3259,6 +3175,7 @@ packages: call-bind: 1.0.7 es-errors: 1.3.0 get-intrinsic: 1.2.4 + dev: true /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -3324,6 +3241,7 @@ packages: engines: {node: '>= 0.4'} dependencies: define-properties: 1.2.1 + dev: true /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} @@ -3352,6 +3270,7 @@ packages: /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} @@ -3414,27 +3333,6 @@ packages: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} dev: true - /http-proxy-agent@4.0.1: - resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} - engines: {node: '>= 6'} - dependencies: - '@tootallnate/once': 1.1.2 - agent-base: 6.0.2 - debug: 4.3.6 - transitivePeerDependencies: - - supports-color - dev: true - - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.6 - transitivePeerDependencies: - - supports-color - dev: true - /human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -3443,12 +3341,6 @@ packages: /ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - /ignore-walk@3.0.4: - resolution: {integrity: sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==} - dependencies: - minimatch: 3.1.2 - dev: true - /ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} @@ -3499,6 +3391,7 @@ packages: es-errors: 1.3.0 hasown: 2.0.2 side-channel: 1.0.6 + dev: true /is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} @@ -3514,6 +3407,7 @@ packages: dependencies: call-bind: 1.0.7 get-intrinsic: 1.2.4 + dev: true /is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -3523,6 +3417,7 @@ packages: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} dependencies: has-bigints: 1.0.2 + dev: true /is-boolean-object@1.1.2: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} @@ -3530,6 +3425,7 @@ packages: dependencies: call-bind: 1.0.7 has-tostringtag: 1.0.2 + dev: true /is-buffer@1.1.6: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} @@ -3550,12 +3446,14 @@ packages: engines: {node: '>= 0.4'} dependencies: is-typed-array: 1.1.13 + dev: true /is-date-object@1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.2 + dev: true /is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} @@ -3602,12 +3500,14 @@ packages: /is-negative-zero@2.0.3: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} + dev: true /is-number-object@1.0.7: resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.2 + dev: true /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} @@ -3625,12 +3525,14 @@ packages: dependencies: call-bind: 1.0.7 has-tostringtag: 1.0.2 + dev: true /is-shared-array-buffer@1.0.3: resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.7 + dev: true /is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} @@ -3647,12 +3549,14 @@ packages: engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.2 + dev: true /is-symbol@1.0.4: resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} engines: {node: '>= 0.4'} dependencies: has-symbols: 1.0.3 + dev: true /is-typed-array@1.1.13: resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} @@ -3664,6 +3568,7 @@ packages: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} dependencies: call-bind: 1.0.7 + dev: true /is-wsl@3.1.0: resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} @@ -3674,6 +3579,7 @@ packages: /isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -4158,7 +4064,6 @@ packages: /js-base64@3.7.7: resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} - dev: false /js-crypto-aes@1.0.6: resolution: {integrity: sha512-E2hu9z5+YtpDg9Un/bDfmH+I5dv/8aN+ozxv9L0ybZldcQ9T5iYDbBKdlKGBUKI3IvzoWSBSdnZnhwZaRIN46w==} @@ -4597,6 +4502,7 @@ packages: optional: true dependencies: whatwg-url: 5.0.0 + dev: false /node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} @@ -4650,10 +4556,12 @@ packages: /object-inspect@1.13.1: resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: true /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} + dev: true /object.assign@4.1.5: resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} @@ -4663,6 +4571,7 @@ packages: define-properties: 1.2.1 has-symbols: 1.0.3 object-keys: 1.1.1 + dev: true /object.fromentries@2.0.8: resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} @@ -4951,10 +4860,6 @@ packages: sisteransi: 1.0.5 dev: true - /punycode@1.4.1: - resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} - dev: true - /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -5023,6 +4928,7 @@ packages: define-properties: 1.2.1 es-errors: 1.3.0 set-function-name: 2.0.2 + dev: true /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} @@ -5106,6 +5012,7 @@ packages: get-intrinsic: 1.2.4 has-symbols: 1.0.3 isarray: 2.0.5 + dev: true /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -5117,6 +5024,7 @@ packages: call-bind: 1.0.7 es-errors: 1.3.0 is-regex: 1.1.4 + dev: true /safe-stable-stringify@2.4.3: resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} @@ -5164,6 +5072,7 @@ packages: es-errors: 1.3.0 functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 + dev: true /sha.js@2.4.11: resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} @@ -5213,6 +5122,7 @@ packages: es-errors: 1.3.0 get-intrinsic: 1.2.4 object-inspect: 1.13.1 + dev: true /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -5281,12 +5191,6 @@ packages: escodegen: 1.14.3 dev: false - /stream-events@1.0.5: - resolution: {integrity: sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==} - dependencies: - stubs: 3.0.0 - dev: true - /string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -5311,20 +5215,6 @@ packages: emoji-regex: 9.2.2 strip-ansi: 7.1.0 - /string.prototype.matchall@4.0.10: - resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.5 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - regexp.prototype.flags: 1.5.2 - set-function-name: 2.0.2 - side-channel: 1.0.6 - dev: false - /string.prototype.padend@3.1.5: resolution: {integrity: sha512-DOB27b/2UTTD+4myKUFh+/fXWcu/UDyASIXfg+7VzoCNNGOfWvoyU/x5pvVHr++ztyt/oSYI1BcWBBG/hmlNjA==} engines: {node: '>= 0.4'} @@ -5342,6 +5232,7 @@ packages: define-properties: 1.2.1 es-abstract: 1.23.2 es-object-atoms: 1.0.0 + dev: true /string.prototype.trimend@1.0.8: resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} @@ -5349,6 +5240,7 @@ packages: call-bind: 1.0.7 define-properties: 1.2.1 es-object-atoms: 1.0.0 + dev: true /string.prototype.trimstart@1.0.7: resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} @@ -5356,6 +5248,7 @@ packages: call-bind: 1.0.7 define-properties: 1.2.1 es-abstract: 1.22.5 + dev: true /string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -5403,10 +5296,6 @@ packages: peek-readable: 5.0.0 dev: true - /stubs@3.0.0: - resolution: {integrity: sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==} - dev: true - /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -5432,20 +5321,6 @@ packages: engines: {node: '>= 0.4'} dev: true - /teeny-request@7.1.1: - resolution: {integrity: sha512-iwY6rkW5DDGq8hE2YgNQlKbptYpY5Nn2xecjQiNjOXWbKzPGUfmeUBCSQbbr306d7Z7U2N0TPl+/SwYRfua1Dg==} - engines: {node: '>=10'} - dependencies: - http-proxy-agent: 4.0.1 - https-proxy-agent: 5.0.1 - node-fetch: 2.7.0 - stream-events: 1.0.5 - uuid: 8.3.2 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - /temp-dir@3.0.0: resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} engines: {node: '>=14.16'} @@ -5513,6 +5388,7 @@ packages: /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: false /ts-api-utils@1.3.0(typescript@5.4.2): resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} @@ -5660,6 +5536,7 @@ packages: call-bind: 1.0.7 es-errors: 1.3.0 is-typed-array: 1.1.13 + dev: true /typed-array-byte-length@1.0.1: resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} @@ -5670,6 +5547,7 @@ packages: gopd: 1.0.1 has-proto: 1.0.3 is-typed-array: 1.1.13 + dev: true /typed-array-byte-offset@1.0.2: resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} @@ -5681,6 +5559,7 @@ packages: gopd: 1.0.1 has-proto: 1.0.3 is-typed-array: 1.1.13 + dev: true /typed-array-length@1.0.5: resolution: {integrity: sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==} @@ -5692,6 +5571,7 @@ packages: has-proto: 1.0.3 is-typed-array: 1.1.13 possible-typed-array-names: 1.0.0 + dev: true /typeorm@0.3.20(ts-node@10.9.2): resolution: {integrity: sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==} @@ -5795,6 +5675,7 @@ packages: has-bigints: 1.0.2 has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 + dev: true /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -5829,12 +5710,6 @@ packages: requires-port: 1.0.0 dev: false - /urlgrey@1.0.0: - resolution: {integrity: sha512-hJfIzMPJmI9IlLkby8QrsCykQ+SXDeO2W5Q9QTW3QpqZVTx4a/K7p8/5q+/isD8vsbVaFgql/gvAoQCRQ2Cb5w==} - dependencies: - fast-url-parser: 1.1.3 - dev: true - /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: true @@ -5849,11 +5724,6 @@ packages: which-typed-array: 1.1.15 dev: false - /uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: true - /uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true @@ -5903,12 +5773,14 @@ packages: /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: false /whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 + dev: false /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -5918,6 +5790,7 @@ packages: is-number-object: 1.0.7 is-string: 1.0.7 is-symbol: 1.0.4 + dev: true /which-typed-array@1.1.15: resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} diff --git a/test/PEX.spec.ts b/test/PEX.spec.ts index daa2d451..fc9070f0 100644 --- a/test/PEX.spec.ts +++ b/test/PEX.spec.ts @@ -208,7 +208,7 @@ describe('evaluate', () => { // Should correctly generate the presentation submission with nested values expect(evaluationResults).toEqual({ areRequiredCredentialsPresent: Status.INFO, - presentation: vps, + presentations: vps, errors: [], warnings: [], value: { @@ -325,7 +325,7 @@ describe('evaluate', () => { expect(evaluationResults).toEqual({ areRequiredCredentialsPresent: Status.INFO, - presentation: vps, + presentations: vps, errors: [], warnings: [], // Should return the same presentation submission if provided @@ -366,7 +366,7 @@ describe('evaluate', () => { expect(evaluationResults).toEqual({ areRequiredCredentialsPresent: Status.INFO, - presentation: vps, + presentations: vps, errors: [], warnings: [], // Should return the same presentation submission if provided @@ -510,7 +510,7 @@ describe('evaluate', () => { expect(evaluationResults).toEqual({ areRequiredCredentialsPresent: Status.ERROR, - presentation: vps, + presentations: vps, errors: [ { message: @@ -606,7 +606,7 @@ describe('evaluate', () => { expect(evaluationResults).toEqual({ areRequiredCredentialsPresent: Status.ERROR, - presentation: vps, + presentations: vps, errors: [ { message: 'Expected all input descriptors (4) to be satisfifed in submission, but found 3. Missing ddc4a62f-73d4-4410-a3d7-b20720a113ed', @@ -684,7 +684,7 @@ describe('evaluate', () => { expect(evaluationResults).toEqual({ areRequiredCredentialsPresent: Status.ERROR, - presentation: vps, + presentations: vps, errors: [ { message: 'Expected all submission requirements (1) to be satisfifed in submission, but found 0.', @@ -742,7 +742,7 @@ describe('evaluate', () => { limitDisclosureSignatureSuites: LIMIT_DISCLOSURE_SIGNATURE_SUITES, }); const result = pex.presentationFrom(pdSchema, vpSimple.verifiableCredential!, { holderDID: HOLDER_DID }); - const presentation = result.presentation as IPresentation; + const presentation = result.presentations[0] as IPresentation; expect(presentation.presentation_submission).toEqual( expect.objectContaining({ definition_id: '32f54163-7166-48f1-93d8-ff217bdb0653', @@ -827,7 +827,7 @@ describe('evaluate', () => { holderDID: 'did:ethr:0x8D0E24509b79AfaB3A74Be1700ebF9769796B489', }, ); - const vp = vpr.verifiablePresentation as IVerifiablePresentation; + const vp = vpr.verifiablePresentations[0] as IVerifiablePresentation; const proof = Array.isArray(vp.proof) ? vp.proof[0] : vp.proof; expect(proof.created).toEqual('2021-12-01T20:10:45.000Z'); expect(proof.proofValue).toEqual('fake'); @@ -844,7 +844,7 @@ describe('evaluate', () => { signatureOptions: getSingatureOptionsMock(), holderDID: 'did:ethr:0x8D0E24509b79AfaB3A74Be1700ebF9769796B489', }); - const vp = vpr.verifiablePresentation as IVerifiablePresentation; + const vp = vpr.verifiablePresentations[0] as IVerifiablePresentation; const proof = Array.isArray(vp.proof) ? vp.proof[0] : vp.proof; expect(proof.created).toEqual('2021-12-01T20:10:45.000Z'); expect(proof.proofValue).toEqual('fake'); @@ -1052,7 +1052,7 @@ describe('evaluate', () => { }); }); - it('when array of presentations is passed, submission is always constructed as external', function () { + it('when array > 1 of presentations is passed, submission is always constructed as external', function () { const pdSchema: PresentationDefinitionV2 = { id: '49768857', input_descriptors: [ @@ -1076,7 +1076,7 @@ describe('evaluate', () => { }; const pex: PEX = new PEX(); const jwtEncodedVp = getFile('./test/dif_pe_examples/vp/vp_permanentResidentCard.jwt'); - const evalResult: PresentationEvaluationResults = pex.evaluatePresentation(pdSchema, [jwtEncodedVp]); + const evalResult: PresentationEvaluationResults = pex.evaluatePresentation(pdSchema, [jwtEncodedVp, jwtEncodedVp]); expect(evalResult.errors).toEqual([]); expect(evalResult.value?.descriptor_map[0]).toEqual({ id: 'prc_type', @@ -1225,7 +1225,7 @@ describe('evaluate', () => { proofOptions: getProofOptionsMock(), signatureOptions: getSingatureOptionsMock(), }); - const vp = vpr.verifiablePresentation as IVerifiablePresentation; + const vp = vpr.verifiablePresentations[0] as IVerifiablePresentation; expect(vp.verifiableCredential?.length).toEqual(1); expect(vp.presentation_submission?.descriptor_map).toEqual([ { diff --git a/test/PEXv1.spec.ts b/test/PEXv1.spec.ts index 75e971bd..b6f45e4a 100644 --- a/test/PEXv1.spec.ts +++ b/test/PEXv1.spec.ts @@ -72,7 +72,7 @@ describe('evaluate', () => { limitDisclosureSignatureSuites: LIMIT_DISCLOSURE_SIGNATURE_SUITES, }); const result = pex.presentationFrom(pdSchema, vpSimple.verifiableCredential!, { holderDID: HOLDER_DID }); - const presentation = result.presentation as IPresentation; + const presentation = result.presentations[0] as IPresentation; expect(presentation.presentation_submission).toEqual( expect.objectContaining({ definition_id: '32f54163-7166-48f1-93d8-ff217bdb0653', @@ -120,7 +120,7 @@ describe('evaluate', () => { signatureOptions: getSingatureOptionsMock(), holderDID: 'did:ethr:0x8D0E24509b79AfaB3A74Be1700ebF9769796B489', }); - const vp = vpr.verifiablePresentation as IVerifiablePresentation; + const vp = vpr.verifiablePresentations[0] as IVerifiablePresentation; const proof = Array.isArray(vp.proof) ? vp.proof[0] : vp.proof; expect(proof.created).toEqual('2021-12-01T20:10:45.000Z'); expect(proof.proofValue).toEqual('fake'); diff --git a/test/PEXv2.spec.ts b/test/PEXv2.spec.ts index 3c384559..edf31ef0 100644 --- a/test/PEXv2.spec.ts +++ b/test/PEXv2.spec.ts @@ -278,7 +278,7 @@ describe('evaluate', () => { signatureOptions: getSingatureOptionsMock(), holderDID: 'did:ethr:0x8D0E24509b79AfaB3A74Be1700ebF9769796B489', }); - const vp = vpr.verifiablePresentation as IVerifiablePresentation; + const vp = vpr.verifiablePresentations[0] as IVerifiablePresentation; const proof = Array.isArray(vp.proof) ? vp.proof[0] : vp.proof; expect(proof.created).toEqual('2021-12-01T20:10:45.000Z'); expect(proof.proofValue).toEqual('fake'); @@ -651,7 +651,7 @@ describe('evaluate', () => { }); expect(vpr.presentationSubmission.descriptor_map).toHaveLength(1); expect(vpr.presentationSubmission.descriptor_map[0].format).toEqual('di_vc'); - const vp = vpr.verifiablePresentation as IVerifiablePresentation; + const vp = vpr.verifiablePresentations[0] as IVerifiablePresentation; const proof = Array.isArray(vp.proof) ? vp.proof[0] : vp.proof; expect(proof.created).toEqual('2021-12-01T20:10:45.000Z'); expect(proof.proofValue).toEqual('fake'); diff --git a/test/SdJwt.spec.ts b/test/SdJwt.spec.ts index 7cc00d46..45a9c714 100644 --- a/test/SdJwt.spec.ts +++ b/test/SdJwt.spec.ts @@ -231,7 +231,7 @@ describe('evaluate', () => { // Must be external for SD-JWT expect(presentationResult.presentationSubmissionLocation).toEqual(PresentationSubmissionLocation.EXTERNAL); - expect(presentationResult.presentation).toEqual({ + expect(presentationResult.presentations[0]).toEqual({ ...decodedSdJwtVcWithDisclosuresRemoved, kbJwt: { header: { @@ -246,7 +246,7 @@ describe('evaluate', () => { }); }); - it('verifiablePresentationFrom and evalutePresentation with vc+sd-jwt format', async () => { + it('verifiablePresentationFrom and evaluatePresentation with vc+sd-jwt format', async () => { const presentationDefinition = getPresentationDefinitionV2(); const selectResults = pex.selectFrom(presentationDefinition, [decodedSdJwtVc]); let kbJwt: string | undefined = undefined; @@ -255,22 +255,22 @@ describe('evaluate', () => { presentationDefinition, selectResults.verifiableCredential!, async (options) => { - const presentation = options.presentation as SdJwtDecodedVerifiableCredential; + const sdJwtCredential = options.presentation as SdJwtDecodedVerifiableCredential; kbJwt = `${Buffer.from( JSON.stringify({ - ...presentation.kbJwt?.header, + ...sdJwtCredential.kbJwt?.header, alg: 'EdDSA', }), ).toString('base64url')}.${Buffer.from( JSON.stringify({ - ...presentation.kbJwt?.payload, + ...sdJwtCredential.kbJwt?.payload, nonce: 'nonce-from-request', // verifier identifier url (not clear yet in HAIP what this should be, but it MUST be present) aud: 'did:web:something', }), ).toString('base64url')}.signature`; - return `${presentation.compactSdJwtVc}${kbJwt}`; + return `${sdJwtCredential.compactSdJwtVc}${kbJwt}`; }, { presentationSubmissionLocation: PresentationSubmissionLocation.EXTERNAL, @@ -294,15 +294,15 @@ describe('evaluate', () => { // Must be external for SD-JWT expect(presentationResult.presentationSubmissionLocation).toEqual(PresentationSubmissionLocation.EXTERNAL); // Expect the KB-JWT to be appended - expect(presentationResult.verifiablePresentation).toEqual(decodedSdJwtVcWithDisclosuresRemoved.compactSdJwtVc + kbJwt); + expect(presentationResult.verifiablePresentations[0]).toEqual(decodedSdJwtVcWithDisclosuresRemoved.compactSdJwtVc + kbJwt); - const evaluateResults = pex.evaluatePresentation(presentationDefinition, presentationResult.verifiablePresentation, { + const evaluateResults = pex.evaluatePresentation(presentationDefinition, presentationResult.verifiablePresentations, { presentationSubmission: presentationResult.presentationSubmission, }); expect(evaluateResults).toEqual({ // Do we want to return the compact variant here? Or the decoded/pretty variant? - presentation: decodedSdJwtVcWithDisclosuresRemoved.compactSdJwtVc + kbJwt, + presentations: [decodedSdJwtVcWithDisclosuresRemoved.compactSdJwtVc + kbJwt], areRequiredCredentialsPresent: Status.INFO, warnings: [], errors: [], diff --git a/test/dif_pe_examples/pdV2/pd-multi-sd-jwt-vp.json b/test/dif_pe_examples/pdV2/pd-multi-sd-jwt-vp.json new file mode 100644 index 00000000..93863921 --- /dev/null +++ b/test/dif_pe_examples/pdV2/pd-multi-sd-jwt-vp.json @@ -0,0 +1,121 @@ +{ + "presentation_definition": { + "id": "Order and ePassport", + "name": "IATA Order / ePassport SD-JWT", + "purpose": "Multi-presentation test for order & ePassport SD-JWT", + "submission_requirements": [ + { + "name": "Order and epass", + "rule": "all", + "from": "A" + } + ], + "input_descriptors": [ + { + "id": "order", + "group": [ + "A" + ], + "format": { + "vc+sd-jwt": { + "sd-jwt_alg_values": [ + "ES256", + "ES384", + "ES512", + "EdDSA" + ] + } + }, + "constraints": { + "limit_disclosure": "required", + "fields": [ + { + "path": [ + "$.vct" + ], + "filter": { + "type": "string", + "pattern": "order_id_vc" + } + }, + { + "path": [ + "$.order.paxSegments[*].operatingCarrierFlightNumber" + ] + }, + { + "path": [ + "$.order.paxSegments[*].scheduledArrivalTime" + ] + }, + { + "path": [ + "$.order.paxSegments[*].scheduledDepartureTime" + ] + } + ] + } + }, + { + "id": "passport credential", + "group": [ + "A" + ], + "format": { + "vc+sd-jwt": { + "sd-jwt_alg_values": ["ES256", "ES384", "ES512", "EdDSA"] + } + }, + "constraints": { + "limit_disclosure": "required", + "fields": [ + { + "path": [ + "$.vct" + ], + "filter": { + "type": "string", + "pattern": "epassport_copy_vc" + } + }, + { + "path": [ + "$.electronicPassport.dataGroup1.holdersName" + ] + }, + { + "path": [ + "$.electronicPassport.dataGroup1.sexCode" + ] + }, + { + "path": [ + "$.electronicPassport.dataGroup1.birthdate" + ] + }, + { + "path": [ + "$.electronicPassport.dataGroup1.natlCode" + ] + }, + { + "path": [ + "$.electronicPassport.dataGroup1.passportNumberIdentifier" + ] + }, + { + "path": [ + "$.electronicPassport.dataGroup1.issuerCode" + ] + }, + { + "path": [ + "$.electronicPassport.dataGroup1.expiryDate" + ] + } + ] + } + } + ] + } +} diff --git a/test/dif_pe_examples/vc/vc-iata-epassport-sd.jwt b/test/dif_pe_examples/vc/vc-iata-epassport-sd.jwt new file mode 100644 index 00000000..bc623aa6 --- /dev/null +++ b/test/dif_pe_examples/vc/vc-iata-epassport-sd.jwt @@ -0,0 +1 @@ +eyJ0eXAiOiJ2YytzZC1qd3QiLCJraWQiOiJkaWQ6d2ViOmFnZW50Lm5iLmRldi5zcGhlcmVvbi5jb20jMDJkMWM2ZDY5ZGFjYjQxZTYwODk5YTdlOGNkYTM5ZjEyYTI2NjZmYzljMzRjNDM3YjFmNzRmNjFjZjUwZDk1YzYwIiwiYWxnIjoiRVMyNTYifQ.eyJlbGVjdHJvbmljUGFzc3BvcnQiOnsiZGF0YUdyb3VwMSI6eyJfc2QiOlsiQm12YXloQ3ExeUJWZ0tWbi1IRURVYnM2SnhZcDQ2RXpYRFFjeTU0TklwWSIsIkRaRjk5S3c2UWFILVBCdUtkRThiNVRpeDZGckpDcURLRHd3UjFOM0lYRFkiLCJGNy1vZm1MbjJIRmQzblNPLTlyRzZEQ0dJYWMwNUQ3Zmh0cDZoYWUzYzBVIiwiTG55ajhWcUJWdU5XWU5jWFJZaXpZRUE2c0J0TDdsY3ZXMFJkeWFXLWh0YyIsIk5LdkZOTWdwSDRrdnp6TzJQRkYyWURwZWpuUWJ0ZWdSeGFSYTJZbS1ZZWMiLCJicXVYTWF0Y2lOeEJCMXl0Wlk0WWtwSEhYZ1QxN1dKM2NCbndxYXFKY0hZIiwibDYwV3l6YVVpU0NoblRuaGZFdHVWUjM1WWJOdUJldDg3WnFkeWtOeXAtcyIsIm9PV1JPT2pfMVR1S1FJR3VGSzJoVzN1WFhBalpGZDVpb2VxWlRZS1NrakUiXX0sImRhdGFHcm91cDJFbmNvZGVkRmFjZUJpb21ldHJpY3MiOnsiX3NkIjpbInh2bHBRdTlIQlJPaWJGV2JNOVZST3BBOGRJaVFIT3lnYm1TOTlXLTQ5bUkiXX0sImRvY1NlY3VyaXR5T2JqZWN0Ijp7Il9zZCI6WyItQy1aQzltaXBmcU8yNTlCLTc5Uk44WVNEQnY4LTQyM0xseFZJWHBGWjJRIiwiRDlLUWdEQ29WNDctY0dVUzlzU1BsajFxem5WMnJ2MF9KYlJYSF9BTGszSSIsIkc0cC1tTnRWYkhXTHdGRkhldW04YkpiXzVadkRlWjBxYzhZcXJDbVU1aVkiXX0sImRhdGFHcm91cDE1Ijp7ImFjdGl2ZUF1dGhlbnRpY2F0aW9uIjp7Il9zZCI6WyJTbUxHdEVEZDgyOUo0NGk0ZnJwRU1nMldUTzY2MmRoNHNRdWw1VGVzNHVnIl19fSwiZGlnaXRhbFRyYXZlbENyZWRlbnRpYWwiOnsiX3NkIjpbIlJGNVI2ODVfc0pQYzFhSTQxUktHYllZRkROcy1ZaUJNenZOTUNNakkwZHciXX19LCJ2Y3QiOiJlcGFzc3BvcnRfY29weV92YyIsInR5cGUiOiJlcGFzc3BvcnRfY29weV92YyIsImV4cGlyYXRpb25EYXRlIjoiMjAyNS0wOS0yNlQxNjowMDozMi44MjRaIiwiY25mIjp7ImtpZCI6ImRpZDpqd2s6ZXlKaGJHY2lPaUpGVXpJMU5pSXNJblZ6WlNJNkluTnBaeUlzSW10MGVTSTZJa1ZESWl3aVkzSjJJam9pVUMweU5UWWlMQ0o0SWpvaVdVTTVhRTFrZVVOU1ZYQndibXB6V25sUGJIbDJkbXBDWTJKTmRXNU5iM1p4ZFMxSlZVSlBkMVZoWXlJc0lua2lPaUptZVc5WFJFOVpNR1pYUkhSaVduTjRlRXMwVlhKTVpHYzVjMkpMUlhscWExZDNVMDk2ZFVReExVdG5JbjAjMCJ9LCJpc3MiOiJkaWQ6d2ViOmFnZW50Lm5iLmRldi5zcGhlcmVvbi5jb20iLCJpYXQiOjE3Mjc3OTg0MzIsIl9zZF9hbGciOiJTSEEtMjU2In0.8qEexTgk2grLk8sC01SS6wid7nKPoDdOxQHbalazTo3F83PE2alcJWOHyJSa2cIXEAqMGgcqCXd_XljuWKYG8Q~WyIwMDY0NDUzNS03YWM3LTRmZDctYmZlMi01MmQ1MTRmZTAzYmYiLCJiaXJ0aGRhdGUiLCIyMDI0LTEwLTA5Il0~WyI0ZmNiOTA5Ny1kOGI2LTQzODEtYTM5Yi1lYjgxZjBkOWUxNDgiLCJleHBpcnlEYXRlIiwiMjAyNC0xMC0xMCJd~WyIzODY4ZjNlMS02NzY4LTQ0OTAtYjI2NS03NGI4N2IxNmRiZWUiLCJzZXhDb2RlIiwiZGQiXQ~WyIyZDc4NGVhZC03ODM3LTQ2NmItOTczMS02MTMwYmNiMmIyOTEiLCJob2xkZXJzTmFtZSIsImRkIl0~WyJmZTY3YmU4YS1iNmZmLTQ1MTAtYWRlZi0yMDMyMmRjMjdkZWUiLCJpc3N1ZXJDb2RlIiwiZCJd~WyI4MTYyODBiMC1hNTE3LTQwZjYtYjk4Yi02N2M1ZTBiZDlhMTIiLCJuYXRsQ29kZSIsImQiXQ~WyJjZWQ2OWEwMS0wNjhjLTRlZmUtYTM3Ni0yOTYyMjgxMGIxZTkiLCJwYXNzcG9ydE51bWJlcklkZW50aWZpZXIiLCJkIl0~ diff --git a/test/dif_pe_examples/vc/vc-iata-order-sd.jwt b/test/dif_pe_examples/vc/vc-iata-order-sd.jwt new file mode 100644 index 00000000..71f4c30e --- /dev/null +++ b/test/dif_pe_examples/vc/vc-iata-order-sd.jwt @@ -0,0 +1 @@ +eyJ0eXAiOiJ2YytzZC1qd3QiLCJraWQiOiJkaWQ6d2ViOmFnZW50Lm5iLmRldi5zcGhlcmVvbi5jb20jMDJkMWM2ZDY5ZGFjYjQxZTYwODk5YTdlOGNkYTM5ZjEyYTI2NjZmYzljMzRjNDM3YjFmNzRmNjFjZjUwZDk1YzYwIiwiYWxnIjoiRVMyNTYifQ.eyJvcmRlciI6eyJfc2QiOlsiWjhWVGlZd2tTa3lHaC1yMWNQSVlwRTJjNVpfS1dtU0pnQlJjUkNpVlJJVSIsImJBRFQtRFZTam5HZnVvdnItRHFVYUxPaGVvOUpKMWxDUDBKMjh2dkRoU0EiLCJmQmVzN2lIRU85VUxMSGRQRnpyRHBYenExbzdpSXhYOVBzNTViS3lCN0h3IiwiaDlablNxU2FkbGxmWEcxaHhWOFRsMEdqdkFBM1lEMzItaHg4MHZhSW9UMCIsInNKWWxiMmQ1czdaLTBpTG1FSUdPTERaODhVeC1hd2lGeThzU0M1OWk4NUUiXX0sInZjdCI6Im9yZGVyX2lkX3ZjIiwidHlwZSI6Im9yZGVyX2lkX3ZjIiwiZXhwaXJhdGlvbkRhdGUiOiIyMDI1LTA5LTI4VDAyOjExOjMzLjQ1NloiLCJjbmYiOnsia2lkIjoiZGlkOmp3azpleUpoYkdjaU9pSkZVekkxTmlJc0luVnpaU0k2SW5OcFp5SXNJbXQwZVNJNklrVkRJaXdpWTNKMklqb2lVQzB5TlRZaUxDSjRJam9pV1VNNWFFMWtlVU5TVlhCd2JtcHpXbmxQYkhsMmRtcENZMkpOZFc1TmIzWnhkUzFKVlVKUGQxVmhZeUlzSW5raU9pSm1lVzlYUkU5Wk1HWlhSSFJpV25ONGVFczBWWEpNWkdjNWMySkxSWGxxYTFkM1UwOTZkVVF4TFV0bkluMCMwIn0sImlzcyI6ImRpZDp3ZWI6YWdlbnQubmIuZGV2LnNwaGVyZW9uLmNvbSIsImlhdCI6MTcyNzkyMTQ5MywiX3NkX2FsZyI6IlNIQS0yNTYifQ.2J_jrFZcuITiAYlAwDx_KmBoSHIwyIl-sy0B6-lt5kJpyZBaEjDS5fKeufiLFL30abiqKT1W03Y5tyDoNuDgjQ~WyJiZDZhMjRjMi01ZjZlLTQ1MjItODdiZC0zYjk4NTA5OWNiNWUiLCJwYXhTZWdtZW50cyIsW3siZGVzdFN0YXRpb25JQVRBTG9jYXRpb25Db2RlIjoiSUFUQTMyNjIzNiIsImZsaWdodElkZW50aWZpZXJEYXRlIjoiMzAxMDIwMDAiLCJvcGVyYXRpbmdDYXJyaWVyQWlybGluZURlc2lnQ29kZSI6IklBVEE0Mzc2NDU4NDU4Iiwib3BlcmF0aW5nQ2FycmllckZsaWdodE51bWJlciI6IjIzNjUiLCJvcmlnaW5TdGF0aW9uSUFUQUxvY2F0aW9uQ29kZSI6IklOMzQ2NzciLCJib29raW5nU3RhdHVzQ29kZSI6IkNORiIsInNjaGVkdWxlZEFycml2YWxUaW1lIjoiMzAxMDIwMDAiLCJzY2hlZHVsZWREZXBhcnR1cmVUaW1lIjoiVEVTVDMyNjM0NjcifV1d~ diff --git a/test/evaluation/check-scenario-1.spec.ts b/test/evaluation/check-scenario-1.spec.ts index fad513eb..01928b3d 100644 --- a/test/evaluation/check-scenario-1.spec.ts +++ b/test/evaluation/check-scenario-1.spec.ts @@ -244,7 +244,7 @@ describe('1st scenario', () => { which is wrong in the case of our example, because the index of our verifiableCredential is no longer #2, but it's "1" */ const presentationResult = pex.presentationFrom(pd, [holderWallet.verifiableCredentials[2]], { holderDID: 'did:didMethod:2021112400' }); - const presentation = presentationResult.presentation as IPresentation; + const presentation = presentationResult.presentations[0] as IPresentation; expect(presentation!.presentation_submission!.definition_id).toEqual('31e2f0f1-6b70-411d-b239-56aed5321884'); expect(presentation!.presentation_submission!.descriptor_map.map((dm) => dm.id).sort()).toEqual([ '867bfe7a-5b91-46b2-9ba4-70028b8d9cc8', diff --git a/test/evaluation/selectFrom.spec.ts b/test/evaluation/selectFrom.spec.ts index 149aaae7..3c44f9b0 100644 --- a/test/evaluation/selectFrom.spec.ts +++ b/test/evaluation/selectFrom.spec.ts @@ -1,26 +1,38 @@ +import { createHash } from 'crypto'; import fs from 'fs'; +import { SDJwt } from '@sd-jwt/core'; import { Rules } from '@sphereon/pex-models'; import { IVerifiableCredential, WrappedVerifiableCredential } from '@sphereon/ssi-types'; -import { Status } from '../../lib'; +import { PEX, Status } from '../../lib'; import { EvaluationClientWrapper } from '../../lib/evaluation'; import { SubmissionRequirementMatchType } from '../../lib/evaluation/core'; -import { InternalPresentationDefinitionV1, SSITypesBuilder } from '../../lib/types'; +import { InternalPresentationDefinitionV1, InternalPresentationDefinitionV2, SSITypesBuilder } from '../../lib/types'; import PexMessages from '../../lib/types/Messages'; +export const hasher = (data: string) => createHash('sha256').update(data).digest(); + function getFile(path: string) { - return JSON.parse(fs.readFileSync(path, 'utf-8')); + return fs.readFileSync(path, 'utf-8'); +} + +function getFileAsJson(path: string) { + return JSON.parse(getFile(path)); } const dids = ['did:example:ebfeb1f712ebc6f1c276e12ec21']; const LIMIT_DISCLOSURE_SIGNATURE_SUITES = ['BbsBlsSignatureProof2020']; +const pex = new PEX({ + hasher, +}); + describe('selectFrom tests', () => { it('Evaluate submission requirements all from group A', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/resources/sr_rules.json').presentation_definition; - const vpSimple = getFile('./test/dif_pe_examples/vp/vp_general.json'); + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/resources/sr_rules.json').presentation_definition; + const vpSimple = getFileAsJson('./test/dif_pe_examples/vp/vp_general.json'); const wvcs: WrappedVerifiableCredential[] = SSITypesBuilder.mapExternalVerifiableCredentialsToWrappedVcs([ vpSimple.verifiableCredential[0], vpSimple.verifiableCredential[1], @@ -122,9 +134,9 @@ describe('selectFrom tests', () => { }); it('Evaluate without submission requirements', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/resources/sr_rules.json').presentation_definition; + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/resources/sr_rules.json').presentation_definition; delete pdSchema.submission_requirements; - const vpSimple = getFile('./test/dif_pe_examples/vp/vp_general.json'); + const vpSimple = getFileAsJson('./test/dif_pe_examples/vp/vp_general.json'); const wvcs: WrappedVerifiableCredential[] = SSITypesBuilder.mapExternalVerifiableCredentialsToWrappedVcs([ vpSimple.verifiableCredential[0], vpSimple.verifiableCredential[1], @@ -141,8 +153,8 @@ describe('selectFrom tests', () => { }); it('Evaluate submission requirements min 2 from group B', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/resources/sr_rules.json').presentation_definition; - const vpSimple = getFile('./test/dif_pe_examples/vp/vp_general.json'); + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/resources/sr_rules.json').presentation_definition; + const vpSimple = getFileAsJson('./test/dif_pe_examples/vp/vp_general.json'); pdSchema!.submission_requirements = [pdSchema!.submission_requirements![1]]; const pd = SSITypesBuilder.modelEntityToInternalPresentationDefinitionV1(pdSchema); const evaluationClientWrapper: EvaluationClientWrapper = new EvaluationClientWrapper(); @@ -214,8 +226,8 @@ describe('selectFrom tests', () => { }); it('Evaluate submission requirements either all from group A or 2 from group B', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/resources/sr_rules.json').presentation_definition; - const vpSimple = getFile('./test/dif_pe_examples/vp/vp_general.json'); + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/resources/sr_rules.json').presentation_definition; + const vpSimple = getFileAsJson('./test/dif_pe_examples/vp/vp_general.json'); pdSchema!.submission_requirements = [pdSchema!.submission_requirements![2]]; const pd = SSITypesBuilder.modelEntityToInternalPresentationDefinitionV1(pdSchema); const evaluationClientWrapper: EvaluationClientWrapper = new EvaluationClientWrapper(); @@ -233,8 +245,8 @@ describe('selectFrom tests', () => { }); it('Evaluate submission requirements max 2 from group B', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/resources/sr_rules.json').presentation_definition; - const vpSimple = getFile('./test/dif_pe_examples/vp/vp_general.json'); + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/resources/sr_rules.json').presentation_definition; + const vpSimple = getFileAsJson('./test/dif_pe_examples/vp/vp_general.json'); pdSchema!.submission_requirements = [pdSchema!.submission_requirements![3]]; const pd = SSITypesBuilder.modelEntityToInternalPresentationDefinitionV1(pdSchema); const evaluationClientWrapper: EvaluationClientWrapper = new EvaluationClientWrapper(); @@ -306,8 +318,8 @@ describe('selectFrom tests', () => { }); it('Evaluate submission requirements all from group A and 2 from group B', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/resources/sr_rules.json').presentation_definition; - const vpSimple = getFile('./test/dif_pe_examples/vp/vp_general.json'); + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/resources/sr_rules.json').presentation_definition; + const vpSimple = getFileAsJson('./test/dif_pe_examples/vp/vp_general.json'); pdSchema!.submission_requirements = [pdSchema!.submission_requirements![8]]; const pd = SSITypesBuilder.modelEntityToInternalPresentationDefinitionV1(pdSchema); const evaluationClientWrapper: EvaluationClientWrapper = new EvaluationClientWrapper(); @@ -429,8 +441,8 @@ describe('selectFrom tests', () => { }); it('Evaluate submission requirements min 1: (all from group A or 2 from group B)', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/resources/sr_rules.json').presentation_definition; - const vpSimple = getFile('./test/dif_pe_examples/vp/vp_general.json'); + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/resources/sr_rules.json').presentation_definition; + const vpSimple = getFileAsJson('./test/dif_pe_examples/vp/vp_general.json'); pdSchema!.submission_requirements = [pdSchema!.submission_requirements![9]]; const pd = SSITypesBuilder.modelEntityToInternalPresentationDefinitionV1(pdSchema); const evaluationClientWrapper: EvaluationClientWrapper = new EvaluationClientWrapper(); @@ -553,8 +565,8 @@ describe('selectFrom tests', () => { }); it('Evaluate submission requirements max 2: (all from group A and 2 from group B)', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/resources/sr_rules.json').presentation_definition; - const vpSimple = getFile('./test/dif_pe_examples/vp/vp_general.json'); + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/resources/sr_rules.json').presentation_definition; + const vpSimple = getFileAsJson('./test/dif_pe_examples/vp/vp_general.json'); pdSchema!.submission_requirements = [pdSchema!.submission_requirements![10]]; const pd = SSITypesBuilder.modelEntityToInternalPresentationDefinitionV1(pdSchema); const evaluationClientWrapper: EvaluationClientWrapper = new EvaluationClientWrapper(); @@ -677,8 +689,8 @@ describe('selectFrom tests', () => { }); it('Evaluate submission requirements min 3 from group B', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/resources/sr_rules.json').presentation_definition; - const vpSimple = getFile('./test/dif_pe_examples/vp/vp_general.json'); + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/resources/sr_rules.json').presentation_definition; + const vpSimple = getFileAsJson('./test/dif_pe_examples/vp/vp_general.json'); pdSchema!.submission_requirements = [pdSchema!.submission_requirements![4]]; const pd = SSITypesBuilder.modelEntityToInternalPresentationDefinitionV1(pdSchema); const evaluationClientWrapper: EvaluationClientWrapper = new EvaluationClientWrapper(); @@ -788,8 +800,8 @@ describe('selectFrom tests', () => { }); it('Evaluate submission requirements max 1 from group B', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/resources/sr_rules.json').presentation_definition; - const vpSimple = getFile('./test/dif_pe_examples/vp/vp_general.json'); + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/resources/sr_rules.json').presentation_definition; + const vpSimple = getFileAsJson('./test/dif_pe_examples/vp/vp_general.json'); pdSchema!.submission_requirements = [pdSchema!.submission_requirements![5]]; const pd = SSITypesBuilder.modelEntityToInternalPresentationDefinitionV1(pdSchema); const evaluationClientWrapper: EvaluationClientWrapper = new EvaluationClientWrapper(); @@ -819,8 +831,8 @@ describe('selectFrom tests', () => { }); it('Evaluate submission requirements exactly 1 from group B', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/resources/sr_rules.json').presentation_definition; - const vpSimple = getFile('./test/dif_pe_examples/vp/vp_general.json'); + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/resources/sr_rules.json').presentation_definition; + const vpSimple = getFileAsJson('./test/dif_pe_examples/vp/vp_general.json'); pdSchema!.submission_requirements = [pdSchema!.submission_requirements![6]]; const pd = SSITypesBuilder.modelEntityToInternalPresentationDefinitionV1(pdSchema); const evaluationClientWrapper: EvaluationClientWrapper = new EvaluationClientWrapper(); @@ -840,8 +852,8 @@ describe('selectFrom tests', () => { }); it('Evaluate submission requirements all from group B', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/resources/sr_rules.json').presentation_definition; - const vpSimple = getFile('./test/dif_pe_examples/vp/vp_general.json'); + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/resources/sr_rules.json').presentation_definition; + const vpSimple = getFileAsJson('./test/dif_pe_examples/vp/vp_general.json'); pdSchema!.submission_requirements = [pdSchema!.submission_requirements![7]]; const pd = SSITypesBuilder.modelEntityToInternalPresentationDefinitionV1(pdSchema); const evaluationClientWrapper: EvaluationClientWrapper = new EvaluationClientWrapper(); @@ -861,8 +873,8 @@ describe('selectFrom tests', () => { }); it('Evaluate submission requirements min 3: (all from group A or 2 from group B + unexistent)', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/resources/sr_rules.json').presentation_definition; - const vpSimple = getFile('./test/dif_pe_examples/vp/vp_general.json'); + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/resources/sr_rules.json').presentation_definition; + const vpSimple = getFileAsJson('./test/dif_pe_examples/vp/vp_general.json'); pdSchema!.submission_requirements = [pdSchema!.submission_requirements![11]]; const pd = SSITypesBuilder.modelEntityToInternalPresentationDefinitionV1(pdSchema); pd.submission_requirements![0].min = 1; @@ -910,8 +922,8 @@ describe('selectFrom tests', () => { }); it('Evaluate submission requirements max 1: (all from group A and 2 from group B)', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/resources/sr_rules.json').presentation_definition; - const vpSimple = getFile('./test/dif_pe_examples/vp/vp_general.json'); + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/resources/sr_rules.json').presentation_definition; + const vpSimple = getFileAsJson('./test/dif_pe_examples/vp/vp_general.json'); pdSchema!.submission_requirements = [pdSchema!.submission_requirements![12]]; const pd = SSITypesBuilder.modelEntityToInternalPresentationDefinitionV1(pdSchema); const evaluationClientWrapper: EvaluationClientWrapper = new EvaluationClientWrapper(); @@ -961,9 +973,11 @@ describe('selectFrom tests', () => { }); it('Evaluate case without presentation submission', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/dif_pe_examples/pdV1/pd-PermanentResidentCard.json').presentation_definition; + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson( + './test/dif_pe_examples/pdV1/pd-PermanentResidentCard.json', + ).presentation_definition; const pd = SSITypesBuilder.modelEntityToInternalPresentationDefinitionV1(pdSchema); - const verifiableCredential = getFile('./test/dif_pe_examples/vc/vc-PermanentResidentCard.json'); + const verifiableCredential = getFileAsJson('./test/dif_pe_examples/vc/vc-PermanentResidentCard.json'); const wvcs: WrappedVerifiableCredential[] = SSITypesBuilder.mapExternalVerifiableCredentialsToWrappedVcs([verifiableCredential]); const evaluationClientWrapper: EvaluationClientWrapper = new EvaluationClientWrapper(); const result = evaluationClientWrapper.selectFrom(pd, wvcs, { @@ -982,10 +996,12 @@ describe('selectFrom tests', () => { }); it('Evaluate driver license name result', () => { - const pdSchema: InternalPresentationDefinitionV1 = getFile('./test/dif_pe_examples/pdV1/pd_driver_license_name.json') + const pdSchema: InternalPresentationDefinitionV1 = getFileAsJson('./test/dif_pe_examples/pdV1/pd_driver_license_name.json') .presentation_definition as InternalPresentationDefinitionV1; const pd = SSITypesBuilder.modelEntityToInternalPresentationDefinitionV1(pdSchema); - const verifiableCredential: IVerifiableCredential = getFile('./test/dif_pe_examples/vc/vc-PermanentResidentCard.json') as IVerifiableCredential; + const verifiableCredential: IVerifiableCredential = getFileAsJson( + './test/dif_pe_examples/vc/vc-PermanentResidentCard.json', + ) as IVerifiableCredential; const wvcs: WrappedVerifiableCredential[] = SSITypesBuilder.mapExternalVerifiableCredentialsToWrappedVcs([verifiableCredential]); const evaluationClientWrapper: EvaluationClientWrapper = new EvaluationClientWrapper(); const result = evaluationClientWrapper.selectFrom(pd, wvcs, { @@ -995,4 +1011,27 @@ describe('selectFrom tests', () => { expect(result!.errors!.length).toEqual(0); expect(result!.matches![0]!.name).toEqual("Name on driver's license"); }); + + it('iata test1', async function () { + const pdSchema: InternalPresentationDefinitionV2 = getFileAsJson('./test/dif_pe_examples/pdV2/pd-multi-sd-jwt-vp.json').presentation_definition; + const vcs: string[] = []; + vcs.push(getFile('test/dif_pe_examples/vc/vc-iata-order-sd.jwt').replace(/(\r\n|\n|\r)/gm, '')); + vcs.push(getFile('test/dif_pe_examples/vc/vc-iata-epassport-sd.jwt').replace(/(\r\n|\n|\r)/gm, '')); + const pd = SSITypesBuilder.modelEntityInternalPresentationDefinitionV2(pdSchema); + const evaluationClientWrapper: EvaluationClientWrapper = new EvaluationClientWrapper(); + const wvcs: WrappedVerifiableCredential[] = SSITypesBuilder.mapExternalVerifiableCredentialsToWrappedVcs(vcs, hasher); + const result = evaluationClientWrapper.selectFrom(pd, wvcs, { + holderDIDs: ['FAsYneKJhWBP2n5E21ZzdY'], + limitDisclosureSignatureSuites: LIMIT_DISCLOSURE_SIGNATURE_SUITES, + }); + expect(result.areRequiredCredentialsPresent).toBe(Status.INFO); + + pex.evaluateCredentials(pd, result.verifiableCredential!); + const presentationResult = pex.presentationFrom(pd, result.verifiableCredential!); + const cred = await SDJwt.fromEncode(presentationResult.presentations[1].compactSdJwtVc, hasher); + const claims = await cred.getClaims(hasher); + console.log(claims); + expect(presentationResult).toBeDefined(); + // TODO finish test + }); }); diff --git a/test/thirdParty/Gataca.spec.ts b/test/thirdParty/Gataca.spec.ts index 1e72d86d..aa431b9f 100644 --- a/test/thirdParty/Gataca.spec.ts +++ b/test/thirdParty/Gataca.spec.ts @@ -60,7 +60,7 @@ describe('evaluate gataca tests', () => { selectFromResult.verifiableCredential as IVerifiableCredential[], undefined, ); - const presentation = presentationFromResult.presentation as IPresentation; + const presentation = presentationFromResult.presentations[0] as IPresentation; expect(presentation.presentation_submission?.descriptor_map).toEqual([ { format: 'ldp_vc', @@ -136,7 +136,7 @@ describe('evaluate gataca tests', () => { selectFromResult.verifiableCredential as IVerifiableCredential[], undefined, ); - const presentation = presentationFromResult.presentation as IPresentation; + const presentation = presentationFromResult.presentations[0] as IPresentation; expect(presentation.presentation_submission?.descriptor_map).toEqual([ { format: 'ldp_vc', diff --git a/test/thirdParty/JGiter.spec.ts b/test/thirdParty/JGiter.spec.ts index db7cb210..c21cf142 100644 --- a/test/thirdParty/JGiter.spec.ts +++ b/test/thirdParty/JGiter.spec.ts @@ -504,7 +504,7 @@ describe('evaluate JGiter tests', () => { expect(selectFrom.matches![1]?.from).toEqual('B'); expect(selectFrom.matches![1]?.vc_path).toEqual(['$.verifiableCredential[1]']); const presentationResult = pex.presentationFrom(pdSchema, selectFrom.verifiableCredential as IVerifiableCredential[]); - const presentation = presentationResult.presentation as IPresentation; + const presentation = presentationResult.presentations[0] as IPresentation; expect(presentation.presentation_submission?.descriptor_map).toEqual([ { id: 'identity_input', @@ -544,7 +544,7 @@ describe('evaluate JGiter tests', () => { expect(resultEvaluation.errors?.length).toEqual(0); expect(resultEvaluation.areRequiredCredentialsPresent).toEqual(Status.INFO); const presentationResult = pex.presentationFrom(pdSchema, [resultEvaluation.verifiableCredential[0]]); - const presentation = presentationResult.presentation as IPresentation; + const presentation = presentationResult.presentations[0] as IPresentation; expect(presentation.presentation_submission?.descriptor_map).toEqual([ { id: 'identity_input',