@credo-ts/core 0.7.3 → 0.7.4-alpha-20261028231852

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/build/agent/TrustedIssuerContext.d.mts +11 -1
  2. package/build/agent/TrustedIssuerContext.d.mts.map +1 -1
  3. package/build/agent/TrustedIssuerContext.mjs +7 -0
  4. package/build/agent/TrustedIssuerContext.mjs.map +1 -1
  5. package/build/agent/TrustedIssuersForVerification.d.mts +11 -1
  6. package/build/agent/TrustedIssuersForVerification.d.mts.map +1 -1
  7. package/build/crypto/webcrypto/CredoWalletWebCrypto.d.mts +1 -1
  8. package/build/index.d.mts +3 -3
  9. package/build/index.mjs +2 -2
  10. package/build/modules/dcql/DcqlService.d.mts.map +1 -1
  11. package/build/modules/dcql/DcqlService.mjs +24 -12
  12. package/build/modules/dcql/DcqlService.mjs.map +1 -1
  13. package/build/modules/dids/services/DidResolverService.d.mts +4 -0
  14. package/build/modules/dids/services/DidResolverService.d.mts.map +1 -1
  15. package/build/modules/dids/services/DidResolverService.mjs +21 -5
  16. package/build/modules/dids/services/DidResolverService.mjs.map +1 -1
  17. package/build/modules/sd-jwt-vc/utils.mjs +4 -4
  18. package/build/modules/sd-jwt-vc/utils.mjs.map +1 -1
  19. package/build/modules/vc/W3cCredentialServiceOptions.d.mts +5 -5
  20. package/build/modules/vc/W3cCredentialServiceOptions.d.mts.map +1 -1
  21. package/build/modules/vc/W3cV2CredentialService.d.mts +5 -1
  22. package/build/modules/vc/W3cV2CredentialService.d.mts.map +1 -1
  23. package/build/modules/vc/W3cV2CredentialService.mjs +72 -26
  24. package/build/modules/vc/W3cV2CredentialService.mjs.map +1 -1
  25. package/build/modules/vc/W3cV2CredentialServiceOptions.d.mts +14 -6
  26. package/build/modules/vc/W3cV2CredentialServiceOptions.d.mts.map +1 -1
  27. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.d.mts +0 -18
  28. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.d.mts.map +1 -1
  29. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.mjs +38 -36
  30. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.mjs.map +1 -1
  31. package/build/modules/vc/data-integrity/v2-di-utils.mjs +17 -35
  32. package/build/modules/vc/data-integrity/v2-di-utils.mjs.map +1 -1
  33. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.d.mts +0 -23
  34. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.d.mts.map +1 -1
  35. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.mjs +17 -68
  36. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.mjs.map +1 -1
  37. package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.d.mts.map +1 -1
  38. package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.mjs +11 -17
  39. package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.mjs.map +1 -1
  40. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.d.mts +5 -0
  41. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.d.mts.map +1 -1
  42. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.mjs +18 -4
  43. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.mjs.map +1 -1
  44. package/build/modules/vc/models/W3cV2VerifyResult.d.mts +6 -0
  45. package/build/modules/vc/models/W3cV2VerifyResult.d.mts.map +1 -1
  46. package/build/modules/vc/models/credential/W3cV2EnvelopedVerifiableCredential.d.mts +1 -1
  47. package/build/modules/vc/models/credential/W3cV2EnvelopedVerifiableCredential.d.mts.map +1 -1
  48. package/build/modules/vc/models/credential/W3cV2VerifiableCredential.d.mts +1 -1
  49. package/build/modules/vc/models/credential/W3cV2VerifiableCredential.d.mts.map +1 -1
  50. package/build/modules/vc/resolveSigner.mjs +74 -0
  51. package/build/modules/vc/resolveSigner.mjs.map +1 -0
  52. package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.d.mts.map +1 -1
  53. package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.mjs +16 -18
  54. package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.mjs.map +1 -1
  55. package/build/modules/vc/sd-jwt-vc/disclosureFrame.d.mts +1 -1
  56. package/build/modules/vc/sd-jwt-vc/disclosureFrame.d.mts.map +1 -1
  57. package/build/modules/vc/sd-jwt-vc/disclosureFrame.mjs +2 -1
  58. package/build/modules/vc/sd-jwt-vc/disclosureFrame.mjs.map +1 -1
  59. package/build/modules/vc/v2-jwt-utils.mjs +54 -55
  60. package/build/modules/vc/v2-jwt-utils.mjs.map +1 -1
  61. package/build/modules/x509/X509ModuleConfig.d.mts +5 -13
  62. package/build/modules/x509/X509ModuleConfig.d.mts.map +1 -1
  63. package/build/modules/x509/X509ModuleConfig.mjs +2 -1
  64. package/build/modules/x509/X509ModuleConfig.mjs.map +1 -1
  65. package/build/modules/x509/X509RevocationService.d.mts.map +1 -1
  66. package/build/modules/x509/X509RevocationService.mjs +17 -20
  67. package/build/modules/x509/X509RevocationService.mjs.map +1 -1
  68. package/build/modules/x509/X509Service.mjs +1 -1
  69. package/build/modules/x509/X509Service.mjs.map +1 -1
  70. package/build/modules/x509/X509ServiceOptions.d.mts +4 -6
  71. package/build/modules/x509/X509ServiceOptions.d.mts.map +1 -1
  72. package/build/modules/x509/X509ValidationOptions.d.mts +19 -2
  73. package/build/modules/x509/X509ValidationOptions.d.mts.map +1 -1
  74. package/build/modules/x509/X509ValidationOptions.mjs +21 -1
  75. package/build/modules/x509/X509ValidationOptions.mjs.map +1 -1
  76. package/build/modules/x509/index.d.mts +2 -2
  77. package/build/modules/x509/index.mjs +2 -2
  78. package/build/modules/x509/utils/crlFetcher.mjs +1 -11
  79. package/build/modules/x509/utils/crlFetcher.mjs.map +1 -1
  80. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"DcqlService.mjs","names":["getDcqlVcPresentationsToCreate"],"sources":["../../../src/modules/dcql/DcqlService.ts"],"sourcesContent":["import {\n DcqlCredential,\n DcqlCredentialQuery,\n DcqlMdocCredential,\n DcqlPresentationResult,\n DcqlQuery,\n DcqlSdJwtVcCredential,\n DcqlW3cVcCredential,\n} from 'dcql'\nimport type { AgentContext } from '../../agent'\nimport { injectable } from '../../plugins'\nimport { isNonEmptyArray, type JsonObject, type JsonValue, mapNonEmptyArray } from '../../types'\nimport { asArray, JsonTransformer, TypedArrayEncoder } from '../../utils'\nimport {\n CredentialMultiInstanceUseMode,\n canUseInstanceFromCredentialRecord,\n useInstanceFromCredentialRecord,\n} from '../../utils/credentialUse'\nimport { DidsApi, getPublicJwkFromVerificationMethod, VerificationMethod } from '../dids'\nimport type { VerifiableCredential, VerifiablePresentation } from '../dif-presentation-exchange/index'\nimport {\n Mdoc,\n MdocApi,\n MdocDeviceResponse,\n type MdocNameSpaces,\n MdocRecord,\n type MdocSessionTranscriptOptions,\n} from '../mdoc'\nimport { SdJwtVcApi, SdJwtVcRecord, SdJwtVcService } from '../sd-jwt-vc'\nimport {\n applyDisclosuresForPaths,\n buildDisclosureFrameForPayload,\n buildPresentationFrameForPaths,\n type ClaimPath,\n getClaimPathsForDcqlClaimSet,\n} from '../sd-jwt-vc/disclosureFrame'\nimport {\n ClaimFormat,\n SignatureSuiteRegistry,\n W3cCredentialRecord,\n W3cCredentialRepository,\n W3cCredentialService,\n W3cJsonLdCredentialService,\n W3cJsonLdVerifiableCredential,\n W3cPresentation,\n W3cV2Credential,\n W3cV2CredentialRecord,\n W3cV2CredentialRepository,\n W3cV2CredentialService,\n W3cV2EnvelopedVerifiableCredential,\n W3cV2Presentation,\n} from '../vc'\nimport { purposes } from '../vc/linked-data-proofs/adapters/jsonld-signatures-adapter'\nimport { W3cV2SdJwtCredentialService, W3cV2SdJwtVerifiableCredential } from '../vc/sd-jwt-vc'\nimport { X509Certificate } from '../x509'\nimport { DcqlError } from './DcqlError'\nimport type {\n DcqlCredentialsForRequest,\n DcqlEncodedPresentations,\n DcqlFailedCredential,\n DcqlPresentation,\n DcqlQueryResult,\n DcqlSelectiveDisclosure,\n DcqlValidCredential,\n} from './models'\nimport { dcqlGetPresentationsToCreate as getDcqlVcPresentationsToCreate } from './utils'\n\nexport interface DcqlSelectCredentialsForRequestOptions {\n /**\n * The usage mode to apply to the credentials when selecting credentials.\n *\n * If an usage mode is selected that require a new instance to be used, and there's no\n * new instances available, an error will be thrown.\n *\n * It does not actually select the credential from the record yet, it just filters\n * out records that don't match the filter.\n */\n useMode?: CredentialMultiInstanceUseMode\n}\n\n@injectable()\nexport class DcqlService {\n /**\n * Queries the wallet for credentials that match the given dcql query. This only does an initial query based on the\n * schema of the input descriptors. It does not do any further filtering based on the constraints in the input descriptors.\n */\n private async queryCredentialsForDcqlQuery(\n agentContext: AgentContext,\n dcqlQuery: DcqlQuery\n ): Promise<Array<SdJwtVcRecord | W3cCredentialRecord | W3cV2CredentialRecord | MdocRecord>> {\n const formats = new Set(dcqlQuery.credentials.map((c) => c.format))\n const allRecords: Array<SdJwtVcRecord | W3cCredentialRecord | W3cV2CredentialRecord | MdocRecord> = []\n\n const mdocDoctypes = dcqlQuery.credentials\n .filter((credentialQuery) => credentialQuery.format === 'mso_mdoc')\n .map((c) => c.meta?.doctype_value)\n\n const mdocApi = this.getMdocApi(agentContext)\n if (mdocDoctypes.every((doctype) => doctype !== undefined)) {\n const mdocRecords = await mdocApi.findAllByQuery({\n $or: mdocDoctypes.map((docType) => ({\n docType: docType,\n })),\n })\n allRecords.push(...mdocRecords)\n } else if (formats.has('mso_mdoc')) {\n const mdocRecords = await mdocApi.getAll()\n allRecords.push(...mdocRecords)\n }\n\n const sdJwts = dcqlQuery.credentials.filter(\n (credentialQuery): credentialQuery is DcqlCredentialQuery.SdJwtVc =>\n (credentialQuery.format === 'vc+sd-jwt' && !(credentialQuery.meta && 'type_values' in credentialQuery.meta)) ||\n credentialQuery.format === 'dc+sd-jwt'\n )\n\n const sdJwtVctValues = sdJwts.flatMap((c) => c.meta?.vct_values)\n\n const sdJwtVcApi = this.getSdJwtVcApi(agentContext)\n if (sdJwtVctValues.every((vct) => vct !== undefined)) {\n const sdjwtVcRecords = await sdJwtVcApi.findAllByQuery({\n $or: [\n // Look for direct vct match\n ...sdJwtVctValues.map((vct) => ({\n vct,\n })),\n // Or an extended vct value\n ...sdJwtVctValues.map((vct) => ({\n extendedVctValues: [vct],\n })),\n ],\n })\n allRecords.push(...sdjwtVcRecords)\n } else if (sdJwts.length > 0) {\n const sdJwtVcRecords = await sdJwtVcApi.getAll()\n allRecords.push(...sdJwtVcRecords)\n }\n\n const w3cCredentialRepository = agentContext.dependencyManager.resolve(W3cCredentialRepository)\n if (formats.has('jwt_vc_json')) {\n const w3cRecords = await w3cCredentialRepository.findByQuery(agentContext, {\n claimFormat: ClaimFormat.JwtVc,\n\n // For jwt_vc_json we query the non-expanded types\n $or: dcqlQuery.credentials\n .flatMap((c) => (c.format === 'jwt_vc_json' ? c.meta.type_values : []))\n .map((typeValues) => ({\n types: typeValues,\n })),\n })\n allRecords.push(...w3cRecords)\n }\n\n if (formats.has('ldp_vc')) {\n const w3cRecords = await w3cCredentialRepository.findByQuery(agentContext, {\n claimFormat: ClaimFormat.LdpVc,\n\n // For LDP_VC we query the expanded types\n $or: dcqlQuery.credentials\n .flatMap((c) => (c.format === 'jwt_vc_json' ? c.meta.type_values : []))\n .map((typeValues) => ({\n expandedTypes: typeValues,\n })),\n })\n allRecords.push(...w3cRecords)\n }\n\n const w3cSdJwts = dcqlQuery.credentials.filter(\n (credentialQuery): credentialQuery is DcqlCredentialQuery.W3cVc & { format: 'vc+sd-jwt' } =>\n credentialQuery.format === 'vc+sd-jwt' && !!credentialQuery.meta && 'type_values' in credentialQuery.meta\n )\n\n if (w3cSdJwts.length > 0) {\n const w3cV2CredentialRepository = agentContext.dependencyManager.resolve(W3cV2CredentialRepository)\n\n const w3cV2Records = await w3cV2CredentialRepository.findByQuery(agentContext, {\n claimFormat: ClaimFormat.SdJwtW3cVc,\n $or: dcqlQuery.credentials\n .flatMap((c) => (c.format === 'vc+sd-jwt' && c.meta && 'type_values' in c.meta ? c.meta.type_values : []))\n .map((typeValues) => ({\n types: typeValues,\n })),\n })\n\n allRecords.push(...w3cV2Records)\n }\n\n return allRecords\n }\n\n private getAuthorityForCredential(\n credential: VerifiableCredential | W3cV2EnvelopedVerifiableCredential\n ): DcqlCredential['authority'] {\n if (credential.claimFormat === ClaimFormat.SdJwtDc) {\n const akiValues = (credential.header.x5c as string[] | undefined)\n ?.map((c) => {\n const akiHex = X509Certificate.fromEncodedCertificate(c).authorityKeyIdentifier\n return akiHex ? TypedArrayEncoder.toBase64Url(TypedArrayEncoder.fromHex(akiHex)) : undefined\n })\n .filter((aki) => aki !== undefined)\n\n return akiValues && isNonEmptyArray(akiValues)\n ? ({\n type: 'aki',\n values: akiValues,\n } as const)\n : undefined\n }\n\n if (credential.claimFormat === ClaimFormat.MsoMdoc) {\n const akiValues = credential.issuerSignedCertificateChain\n .map((c) => {\n const akiHex = X509Certificate.fromRawCertificate(c).authorityKeyIdentifier\n return akiHex ? TypedArrayEncoder.toBase64Url(TypedArrayEncoder.fromHex(akiHex)) : undefined\n })\n .filter((aki) => aki !== undefined)\n\n return akiValues && isNonEmptyArray(akiValues)\n ? ({\n type: 'aki',\n values: akiValues,\n } as const)\n : undefined\n }\n\n return undefined\n }\n\n public async getDcqlCredentialRepresentation(\n agentContext: AgentContext,\n presentation: VerifiablePresentation,\n queryCredential: DcqlQuery['credentials'][number]\n ): Promise<DcqlCredential> {\n // SD-JWT credential can be used as both dc+sd-jwt and vc+sd-jwt\n // At some point we might want to look at the header value of the sd-jwt (vc+sd-jwt vc dc+sd-jwt)\n if (presentation.claimFormat === ClaimFormat.SdJwtDc) {\n const requestedVcts = queryCredential.format === 'dc+sd-jwt' ? queryCredential.meta?.vct_values : undefined\n\n let presentationVctValues = [presentation.payload.vct]\n // FIXME: we should probably add an option whether to resolve VCT if we didn't get a direct hit\n if (!requestedVcts?.includes(presentation.payload.vct)) {\n const typeMetadataChain = await agentContext\n .resolve(SdJwtVcService)\n .fetchTypeMetadata(agentContext, presentation, {\n throwErrorOnFetchError: false,\n throwErrorOnUnsupportedVctValue: false,\n })\n\n if (typeMetadataChain) {\n presentationVctValues = typeMetadataChain?.vctValues\n }\n }\n\n return {\n credential_format: queryCredential.format === 'dc+sd-jwt' ? 'dc+sd-jwt' : 'vc+sd-jwt',\n authority: this.getAuthorityForCredential(presentation),\n cryptographic_holder_binding: true,\n vct:\n presentationVctValues.find((presentationVctValue) => requestedVcts?.includes(presentationVctValue)) ??\n presentation.payload.vct,\n claims: presentation.prettyClaims as DcqlSdJwtVcCredential.Claims,\n } satisfies DcqlSdJwtVcCredential\n }\n if (presentation.claimFormat === ClaimFormat.MsoMdoc) {\n if (!presentation.deviceResponse.documents || presentation.deviceResponse.documents.length !== 1) {\n throw new DcqlError('MDOC presentations must contain exactly one document')\n }\n\n return {\n cryptographic_holder_binding: true,\n credential_format: 'mso_mdoc',\n authority: this.getAuthorityForCredential(new Mdoc(presentation.deviceResponse.documents[0].issuerSigned)),\n doctype: presentation.deviceResponse.documents[0].docType,\n namespaces: Object.entries(\n Object.fromEntries(\n presentation.deviceResponse.documents[0].issuerSigned.issuerNamespaces?.issuerNamespaces ?? []\n )\n ).reduce(\n (prev, [key, value]) => ({\n // biome-ignore lint/performance/noAccumulatingSpread: time complexity not relevant here\n ...prev,\n [key]: value.reduce<Record<string, unknown>>(\n // biome-ignore lint/performance/noAccumulatingSpread: time complexity not relevant here\n (prev, curr) => ({ ...prev, [curr.elementIdentifier]: curr.elementValue }),\n {}\n ),\n }),\n {}\n ),\n } satisfies DcqlMdocCredential\n }\n if (presentation.claimFormat === ClaimFormat.JwtVp) {\n const vc = Array.isArray(presentation.verifiableCredential)\n ? presentation.verifiableCredential[0]\n : presentation.verifiableCredential\n\n return {\n cryptographic_holder_binding: true,\n credential_format: 'jwt_vc_json',\n authority: this.getAuthorityForCredential(vc),\n claims: vc.jsonCredential as { [key: string]: JsonValue },\n type: vc.type,\n } satisfies DcqlW3cVcCredential\n }\n if (presentation.claimFormat === ClaimFormat.LdpVp) {\n const vc = Array.isArray(presentation.verifiableCredential)\n ? (presentation.verifiableCredential[0] as W3cJsonLdVerifiableCredential)\n : (presentation.verifiableCredential as W3cJsonLdVerifiableCredential)\n\n const w3cJsonLdCredentialService = agentContext.dependencyManager.resolve(W3cJsonLdCredentialService)\n const expandedTypes = await w3cJsonLdCredentialService.getExpandedTypesForCredential(agentContext, vc)\n\n return {\n cryptographic_holder_binding: true,\n credential_format: 'ldp_vc',\n authority: this.getAuthorityForCredential(vc),\n claims: vc.jsonCredential as DcqlW3cVcCredential.Claims,\n type: expandedTypes,\n } satisfies DcqlW3cVcCredential\n }\n if (presentation.claimFormat === ClaimFormat.SdJwtW3cVp) {\n const firstEntry = Array.isArray(presentation.resolvedPresentation.verifiableCredential)\n ? presentation.resolvedPresentation.verifiableCredential[0]\n : presentation.resolvedPresentation.verifiableCredential\n\n if (!(firstEntry instanceof W3cV2EnvelopedVerifiableCredential)) {\n throw new DcqlError(\n 'Expected an EnvelopedVerifiableCredential entry for vc+sd-jwt presentation claim extraction'\n )\n }\n\n return {\n cryptographic_holder_binding: true,\n credential_format: 'vc+sd-jwt',\n authority: this.getAuthorityForCredential(firstEntry),\n type: asArray(firstEntry.resolvedCredential.type),\n claims: firstEntry.resolvedCredential.toJSON() as { [key: string]: JsonValue },\n } satisfies DcqlW3cVcCredential\n }\n\n throw new DcqlError('Unsupported claim format for presentation')\n }\n\n public async getCredentialsForRequest(agentContext: AgentContext, dcqlQuery: DcqlQuery): Promise<DcqlQueryResult> {\n const credentialRecords = await this.queryCredentialsForDcqlQuery(agentContext, dcqlQuery)\n const credentialRecordsWithFormatDuplicates: typeof credentialRecords = []\n const parsedQuery = DcqlQuery.parse(dcqlQuery)\n\n const dcqlCredentials: DcqlCredential[] = credentialRecords.flatMap((record): DcqlCredential | DcqlCredential[] => {\n if (record.type === 'MdocRecord') {\n credentialRecordsWithFormatDuplicates.push(record)\n\n // We always extract the first mdoc for querying\n const mdoc = record.firstCredential\n\n return {\n authority: this.getAuthorityForCredential(mdoc),\n credential_format: 'mso_mdoc',\n doctype: mdoc.docType,\n namespaces: mdoc.issuerSignedNamespaces,\n cryptographic_holder_binding: true,\n } satisfies DcqlCredential\n }\n\n if (record.type === 'SdJwtVcRecord') {\n const sdJwtVc = record.firstCredential\n const claims = sdJwtVc.prettyClaims as DcqlSdJwtVcCredential.Claims\n\n // To keep correct mapping of input credential index, we add it multiple times here:\n // - for dc+sd-jwt and vc+sd-jwt\n // - for each extended VCT (until we have multi-vct support in DCQL)\n credentialRecordsWithFormatDuplicates.push(\n record,\n record,\n ...record.extendedVctValues.map(() => record),\n ...record.extendedVctValues.map(() => record)\n )\n\n return [\n {\n authority: this.getAuthorityForCredential(sdJwtVc),\n credential_format: 'dc+sd-jwt',\n vct: record.getTags().vct,\n claims,\n cryptographic_holder_binding: true,\n } satisfies DcqlSdJwtVcCredential,\n ...record.extendedVctValues.map(\n (extendedVctValue) =>\n ({\n authority: this.getAuthorityForCredential(sdJwtVc),\n credential_format: 'dc+sd-jwt',\n vct: extendedVctValue,\n claims,\n cryptographic_holder_binding: true,\n }) satisfies DcqlSdJwtVcCredential\n ),\n {\n authority: this.getAuthorityForCredential(sdJwtVc),\n credential_format: 'vc+sd-jwt',\n vct: record.getTags().vct,\n claims,\n cryptographic_holder_binding: true,\n } satisfies DcqlSdJwtVcCredential,\n ...record.extendedVctValues.map(\n (extendedVctValue) =>\n ({\n authority: this.getAuthorityForCredential(sdJwtVc),\n credential_format: 'vc+sd-jwt',\n vct: extendedVctValue,\n claims,\n cryptographic_holder_binding: true,\n }) satisfies DcqlSdJwtVcCredential\n ),\n ] satisfies DcqlSdJwtVcCredential[]\n }\n\n if (record.type === 'W3cCredentialRecord') {\n const firstCredential = record.firstCredential\n credentialRecordsWithFormatDuplicates.push(record)\n if (firstCredential.claimFormat === ClaimFormat.LdpVc) {\n return {\n credential_format: 'ldp_vc',\n authority: this.getAuthorityForCredential(firstCredential),\n type: record.getTags().expandedTypes ?? [],\n claims: firstCredential.jsonCredential as DcqlW3cVcCredential.Claims,\n cryptographic_holder_binding: true,\n } satisfies DcqlW3cVcCredential\n }\n\n return {\n credential_format: 'jwt_vc_json',\n authority: this.getAuthorityForCredential(firstCredential),\n type: firstCredential.type,\n claims: firstCredential.jsonCredential as DcqlW3cVcCredential.Claims,\n cryptographic_holder_binding: true,\n } satisfies DcqlW3cVcCredential\n }\n\n if (record.type === 'W3cV2CredentialRecord') {\n credentialRecordsWithFormatDuplicates.push(record)\n const firstCredential = record.firstCredential\n\n return {\n credential_format: 'vc+sd-jwt',\n authority: this.getAuthorityForCredential(firstCredential),\n type: asArray(firstCredential.resolvedCredential.type),\n claims: firstCredential.resolvedCredential.toJSON() as DcqlW3cVcCredential.Claims,\n cryptographic_holder_binding: true,\n } satisfies DcqlW3cVcCredential\n }\n\n throw new DcqlError('Unsupported record type')\n })\n\n const queryResult = DcqlQuery.query(parsedQuery, dcqlCredentials)\n\n const matchesWithRecord = Object.fromEntries(\n Object.entries(queryResult.credential_matches).map(([credential_query_id, result]) => {\n const failedCredentials = result.failed_credentials\n ? mapNonEmptyArray(result.failed_credentials, (credential) => {\n const record = credentialRecordsWithFormatDuplicates[credential.input_credential_index]\n const updatedCredential: DcqlFailedCredential = {\n ...credential,\n record,\n claims: credential.claims.success\n ? {\n ...credential.claims,\n success: true,\n valid_claim_sets: mapNonEmptyArray(credential.claims.valid_claim_sets, (claimSet) => ({\n ...claimSet,\n ...this.getDisclosedClaimSetOutput(record, claimSet, parsedQuery, credential_query_id),\n })),\n }\n : credential.claims,\n }\n return updatedCredential\n })\n : undefined\n\n // If not success, valid_credentials will be undefined, so we only have to map failed_credentials\n if (!result.success) {\n return [\n credential_query_id,\n {\n ...result,\n failed_credentials: failedCredentials,\n },\n ]\n }\n\n return [\n credential_query_id,\n {\n ...result,\n failed_credentials: failedCredentials,\n valid_credentials: mapNonEmptyArray(result.valid_credentials, (credential) => {\n const record = credentialRecordsWithFormatDuplicates[credential.input_credential_index]\n const updatedCredential: DcqlValidCredential = {\n ...credential,\n record,\n claims: {\n ...credential.claims,\n valid_claim_sets: mapNonEmptyArray(credential.claims.valid_claim_sets, (claimSet) => ({\n ...claimSet,\n ...this.getDisclosedClaimSetOutput(record, claimSet, parsedQuery, credential_query_id),\n })),\n },\n }\n return updatedCredential\n }),\n },\n ]\n })\n )\n\n return {\n ...queryResult,\n credential_matches: matchesWithRecord,\n }\n }\n\n /**\n * What a selectively disclosable credential discloses for the output of a claim set.\n *\n * The output of DCQL only holds the requested claims, while a claim that is not selectively\n * disclosable is always disclosed. So the output is replaced with the claims as the verifier receives\n * them, and `disclosed_paths` added: the paths to those claims in the credential, which are what to\n * disclose when presenting it.\n *\n * Other credentials disclose the output as it is.\n */\n private getDisclosedClaimSetOutput(\n record: DcqlValidCredential['record'],\n claimSet: { output: unknown; valid_claim_indexes?: number[] },\n dcqlQuery: DcqlQuery.Output,\n credentialQueryId: string\n ) {\n // The paths of the claims queries of the claim set, each with the elements a `null` in it selects\n const getClaimPaths = () => {\n const claimsQueries = dcqlQuery.credentials.find((credential) => credential.id === credentialQueryId)?.claims\n const claimsQueryPaths = (claimSet.valid_claim_indexes ?? []).flatMap((index) => {\n const claimsQuery = claimsQueries?.[index]\n // Note path is an array again, we use flatmap, so wrap it in another array, so that if\n // no value is returned ([]) it is not included as undefined in the array\n return claimsQuery && 'path' in claimsQuery ? [claimsQuery.path] : []\n })\n\n return getClaimPathsForDcqlClaimSet(claimsQueryPaths, claimSet.output)\n }\n\n if (record.type === 'SdJwtVcRecord') {\n const { prettyClaims, disclosedPaths } = applyDisclosuresForPaths(record.encoded, getClaimPaths())\n\n return { output: prettyClaims as { [key: string]: JsonValue }, disclosed_paths: disclosedPaths }\n }\n\n if (record.type === 'W3cV2CredentialRecord' && record.firstCredential instanceof W3cV2SdJwtVerifiableCredential) {\n const { prettyClaims, disclosedPaths } = applyDisclosuresForPaths(record.firstCredential.encoded, getClaimPaths())\n\n return {\n // The same shape as the claims DCQL was queried with, which are the credential's JSON\n output: JsonTransformer.fromJSON(prettyClaims, W3cV2Credential, { validate: false }).toJSON() as {\n [key: string]: JsonValue\n },\n disclosed_paths: disclosedPaths,\n }\n }\n\n return {}\n }\n\n public async assertValidDcqlPresentation(\n agentContext: AgentContext,\n dcqlPresentation: DcqlPresentation,\n dcqlQuery: DcqlQuery\n ) {\n const internalDcqlPresentation = Object.fromEntries(\n await Promise.all(\n Object.entries(dcqlPresentation).map(async ([credentialId, presentations]) => {\n const queryCredential = dcqlQuery.credentials.find((c) => c.id === credentialId)\n if (!queryCredential) {\n throw new DcqlError(\n `DCQL presentation contains presentation entry for credential id '${credentialId}', but this id is not present in the DCQL query`\n )\n }\n\n return [\n credentialId,\n await Promise.all(\n presentations.map((presentation) =>\n this.getDcqlCredentialRepresentation(agentContext, presentation, queryCredential)\n )\n ),\n ]\n })\n )\n )\n\n const presentationResult = DcqlPresentationResult.fromDcqlPresentation(internalDcqlPresentation, { dcqlQuery })\n\n if (!presentationResult.can_be_satisfied) {\n throw new DcqlError('Presentations do not satisfy the DCQL query.', {\n additionalMessages: Object.entries(presentationResult.credential_matches ?? {})\n .flatMap(([queryId, match]) =>\n match.success\n ? undefined\n : !match.failed_credentials\n ? `Unable to match query credential '${queryId}'. No prsentations provided`\n : match.failed_credentials.map(\n (failedCredential) =>\n `Presentation at index ${failedCredential.input_credential_index} does not match query credential '${queryId}'. ${JSON.stringify(\n {\n ...(failedCredential.claims.success\n ? {}\n : { claims: failedCredential.claims.failed_claim_sets.map((cs) => cs.issues) }),\n ...(failedCredential.trusted_authorities.success\n ? {}\n : {\n trusted_authorities:\n failedCredential.trusted_authorities.failed_trusted_authorities.map(\n (ta) => ta.issues\n ),\n }),\n ...(failedCredential.meta.success ? {} : { meta: failedCredential.meta.issues }),\n },\n null,\n 2\n )}`\n )\n )\n .filter((message) => message !== undefined),\n })\n }\n\n return presentationResult\n }\n\n private getSelectiveDisclosure(validCredential: DcqlValidCredential): DcqlSelectiveDisclosure {\n const [{ output, disclosed_paths }] = validCredential.claims.valid_claim_sets\n\n return disclosed_paths\n ? { disclosedPaths: disclosed_paths, disclosedPayload: output as JsonObject }\n : { disclosedPayload: output as JsonObject }\n }\n\n private dcqlCredentialForRequestForValidCredential(validCredential: DcqlValidCredential) {\n if (validCredential.record.type === 'MdocRecord') {\n return {\n claimFormat: ClaimFormat.MsoMdoc,\n credentialRecord: validCredential.record,\n disclosedPayload: validCredential.claims.valid_claim_sets[0].output as MdocNameSpaces,\n } as const\n }\n if (validCredential.record.type === 'SdJwtVcRecord') {\n return {\n claimFormat: ClaimFormat.SdJwtDc,\n credentialRecord: validCredential.record,\n ...this.getSelectiveDisclosure(validCredential),\n } as const\n }\n\n if (validCredential.record.type === 'W3cCredentialRecord') {\n return {\n claimFormat: validCredential.record.firstCredential.claimFormat,\n credentialRecord: validCredential.record,\n disclosedPayload: validCredential.record.firstCredential.jsonCredential as JsonObject,\n } as const\n }\n\n if (validCredential.record.type === 'W3cV2CredentialRecord') {\n const claimFormat = validCredential.record.firstCredential.claimFormat\n\n if (claimFormat === ClaimFormat.DiVc) {\n throw new DcqlError('DCQL credential selection does not support W3C V2 Data Integrity credentials yet')\n }\n\n if (claimFormat === ClaimFormat.SdJwtW3cVc) {\n return {\n claimFormat,\n credentialRecord: validCredential.record,\n ...this.getSelectiveDisclosure(validCredential),\n } as const\n }\n\n return {\n claimFormat,\n credentialRecord: validCredential.record,\n disclosedPayload: validCredential.claims.valid_claim_sets[0].output as JsonObject,\n } as const\n }\n\n throw new DcqlError('Unsupported record type for DCQL')\n }\n\n /**\n * Selects the credentials to use based on the output from `getCredentialsForRequest`\n * Use this method if you don't want to manually select the credentials yourself.\n */\n public selectCredentialsForRequest(\n dcqlQueryResult: DcqlQueryResult,\n { useMode = CredentialMultiInstanceUseMode.NewOrFirst }: DcqlSelectCredentialsForRequestOptions = {}\n ): DcqlCredentialsForRequest {\n if (!dcqlQueryResult.can_be_satisfied) {\n throw new DcqlError(\n 'Cannot select the credentials for the dcql query presentation if the request cannot be satisfied'\n )\n }\n\n const credentials: DcqlCredentialsForRequest = {}\n\n if (dcqlQueryResult.credential_sets) {\n credentialSetLoop: for (const credentialSet of dcqlQueryResult.credential_sets) {\n // undefined defaults to true\n if (credentialSet.required === false) continue\n const fullfillableOptions = credentialSet.matching_options\n\n if (!fullfillableOptions) {\n throw new DcqlError('Invalid dcql query result. No option is fullfillable')\n }\n\n for (const fullfillableOption of fullfillableOptions) {\n const optionMatches = fullfillableOption.map((credentialQueryId) => {\n const credentialMatch = dcqlQueryResult.credential_matches[credentialQueryId]\n if (!credentialMatch.success) return undefined\n const match = credentialMatch.valid_credentials.find((match: DcqlValidCredential) =>\n canUseInstanceFromCredentialRecord({ credentialRecord: match.record, useMode })\n )\n\n if (!match) return undefined\n return {\n match,\n credentialQueryId,\n }\n })\n\n if (optionMatches.every((c) => c !== undefined)) {\n for (const { match, credentialQueryId } of optionMatches) {\n credentials[credentialQueryId] = [this.dcqlCredentialForRequestForValidCredential(match)]\n }\n\n continue credentialSetLoop\n }\n }\n\n throw new DcqlError(\n 'Unable to select credentials for credential set. No new credential instance available on any of the available credentials.'\n )\n }\n } else {\n for (const credentialQuery of dcqlQueryResult.credentials) {\n const credentialMatch = dcqlQueryResult.credential_matches[credentialQuery.id]\n if (!credentialMatch.success) {\n throw new DcqlError(\n `Invalid dcql query result for credential query id '${credentialQuery.id}'. Cannot auto-select credentials`\n )\n }\n\n const credential = credentialMatch.valid_credentials.find((match: DcqlValidCredential) =>\n canUseInstanceFromCredentialRecord({ credentialRecord: match.record, useMode })\n )\n if (!credential) {\n throw new DcqlError(\n `Unable to select credential for credential query id '${credentialQuery.id}'. No new credential instance available on any of the available credentials.`\n )\n }\n\n credentials[credentialQuery.id] = [this.dcqlCredentialForRequestForValidCredential(credential)]\n }\n }\n\n return credentials\n }\n\n public validateDcqlQuery(dcqlQuery: DcqlQuery | DcqlQuery.Input | unknown): DcqlQuery {\n const parsed = DcqlQuery.parse(dcqlQuery as DcqlQuery)\n DcqlQuery.validate(parsed)\n return parsed\n }\n\n public async createPresentation(\n agentContext: AgentContext,\n options: {\n credentialQueryToCredential: DcqlCredentialsForRequest\n challenge: string\n domain?: string\n mdocSessionTranscript?: MdocSessionTranscriptOptions\n }\n ): Promise<{\n dcqlPresentation: DcqlPresentation\n encodedDcqlPresentation: DcqlEncodedPresentations\n }> {\n const { domain, challenge, mdocSessionTranscript } = options\n\n const dcqlPresentation: DcqlPresentation = {}\n const encodedDcqlPresentation: DcqlEncodedPresentations = {}\n const vcPresentationsToCreate = getDcqlVcPresentationsToCreate(options.credentialQueryToCredential)\n\n for (const [credentialQueryId, presentationsToCreate] of Object.entries(vcPresentationsToCreate)) {\n for (const presentationToCreate of presentationsToCreate) {\n let createdPresentation: VerifiablePresentation\n let encodedCreatedPresentation: string | Record<string, unknown>\n\n if (presentationToCreate.claimFormat === ClaimFormat.MsoMdoc) {\n const mdocRecord = presentationToCreate.credentialRecord\n if (!mdocSessionTranscript) {\n throw new DcqlError('Missing mdoc session transcript options for creating MDOC presentation.')\n }\n\n const { credentialInstance } = await useInstanceFromCredentialRecord({\n agentContext,\n useMode: presentationToCreate.useMode,\n credentialRecord: mdocRecord,\n })\n\n const deviceResponse = await MdocDeviceResponse.createDeviceResponse(agentContext, {\n mdocs: [credentialInstance],\n documentRequests: [\n {\n docType: mdocRecord.getTags().docType,\n nameSpaces: Object.fromEntries(\n Object.entries(presentationToCreate.disclosedPayload).map(([key, value]) => {\n // FIXME: we need the DCQL query here to get the intent_to_retain from query (currently hardcoded to false)\n return [key, Object.fromEntries(Object.entries(value).map(([key]) => [key, false]))]\n })\n ),\n },\n ],\n sessionTranscriptOptions: mdocSessionTranscript,\n })\n const deviceResponseBase64Url = deviceResponse.encoded\n\n encodedCreatedPresentation = deviceResponseBase64Url\n createdPresentation = MdocDeviceResponse.fromBase64Url(deviceResponseBase64Url)\n } else if (presentationToCreate.claimFormat === ClaimFormat.SdJwtDc) {\n if (!domain) {\n throw new DcqlError('Missing domain property for creating SdJwtVc presentation.')\n }\n\n const { credentialInstance } = await useInstanceFromCredentialRecord({\n agentContext,\n useMode: presentationToCreate.useMode,\n credentialRecord: presentationToCreate.credentialRecord,\n })\n\n const presentationFrame = this.getPresentationFrame(\n typeof credentialInstance === 'string' ? credentialInstance : credentialInstance.compact,\n presentationToCreate\n )\n\n const sdJwtVcApi = this.getSdJwtVcApi(agentContext)\n const presentation = await sdJwtVcApi.present({\n sdJwtVc: credentialInstance,\n presentationFrame,\n verifierMetadata: {\n audience: domain,\n nonce: challenge,\n issuedAt: Math.floor(Date.now() / 1000),\n },\n additionalPayload: presentationToCreate.additionalPayload,\n })\n\n encodedCreatedPresentation = presentation\n createdPresentation = sdJwtVcApi.fromCompact(presentation)\n } else if (presentationToCreate.claimFormat === ClaimFormat.JwtVp) {\n const { credentialInstance } = await useInstanceFromCredentialRecord({\n agentContext,\n useMode: presentationToCreate.useMode,\n credentialRecord: presentationToCreate.credentialRecord,\n })\n\n if (!credentialInstance.credentialSubjectIds[0]) {\n throw new DcqlError('Cannot create presentation for credentials without subject id')\n }\n\n // Determine a suitable verification method for the presentation\n const verificationMethod = await this.getVerificationMethodForSubjectId(\n agentContext,\n credentialInstance.credentialSubjectIds[0]\n )\n\n const w3cCredentialService = agentContext.resolve(W3cCredentialService)\n const w3cPresentation = new W3cPresentation({\n verifiableCredential: [credentialInstance],\n holder: verificationMethod.controller,\n })\n\n const publicJwk = getPublicJwkFromVerificationMethod(verificationMethod)\n\n const signedPresentation = await w3cCredentialService.signPresentation<ClaimFormat.JwtVp>(agentContext, {\n format: ClaimFormat.JwtVp,\n alg: publicJwk.signatureAlgorithm,\n verificationMethod: verificationMethod.id,\n presentation: w3cPresentation,\n challenge,\n domain,\n })\n\n encodedCreatedPresentation = signedPresentation.encoded\n createdPresentation = signedPresentation\n } else if (presentationToCreate.claimFormat === ClaimFormat.LdpVp) {\n const { credentialInstance } = await useInstanceFromCredentialRecord({\n agentContext,\n useMode: presentationToCreate.useMode,\n credentialRecord: presentationToCreate.credentialRecord,\n })\n\n if (!credentialInstance.credentialSubjectIds[0]) {\n throw new DcqlError('Cannot create presentation for credentials without subject id')\n }\n\n // Determine a suitable verification method for the presentation\n const verificationMethod = await this.getVerificationMethodForSubjectId(\n agentContext,\n credentialInstance.credentialSubjectIds[0]\n )\n\n const w3cCredentialService = agentContext.resolve(W3cCredentialService)\n const w3cPresentation = new W3cPresentation({\n verifiableCredential: [credentialInstance],\n holder: verificationMethod.controller,\n })\n\n const signedPresentation = await w3cCredentialService.signPresentation(agentContext, {\n format: ClaimFormat.LdpVp,\n // TODO: we should move the check for which proof to use for a presentation to earlier\n // as then we know when determining which VPs to submit already if the proof types are supported\n // by the verifier, and we can then just add this to the vpToCreate interface\n proofType: this.getProofTypeForLdpVc(agentContext, verificationMethod),\n proofPurpose: new purposes.AuthenticationProofPurpose({ challenge, domain }),\n verificationMethod: verificationMethod.id,\n presentation: w3cPresentation,\n challenge,\n domain,\n })\n\n encodedCreatedPresentation = signedPresentation.encoded\n createdPresentation = signedPresentation\n } else if (presentationToCreate.claimFormat === ClaimFormat.JwtW3cVp) {\n const w3cV2CredentialService = agentContext.resolve(W3cV2CredentialService)\n const firstCredential = presentationToCreate.credentialRecord.firstCredential\n\n if (firstCredential.claimFormat === ClaimFormat.DiVc) {\n throw new DcqlError('DCQL JWT W3C VP creation does not support W3C V2 Data Integrity credentials yet')\n }\n\n const w3cV2Presentation = new W3cV2Presentation({\n holder: firstCredential.resolvedCredential.credentialSubjectIds[0],\n verifiableCredential: [W3cV2EnvelopedVerifiableCredential.fromVerifiableCredential(firstCredential)],\n })\n\n const signedPresentation = await w3cV2CredentialService.signPresentation<ClaimFormat.JwtW3cVp>(agentContext, {\n format: ClaimFormat.JwtW3cVp,\n presentation: w3cV2Presentation,\n challenge,\n domain,\n })\n\n encodedCreatedPresentation = signedPresentation.encoded\n createdPresentation = signedPresentation\n } else if (presentationToCreate.claimFormat === ClaimFormat.SdJwtW3cVp) {\n const presentationFrame = this.getPresentationFrame(\n presentationToCreate.credentialRecord.firstCredential.encoded,\n presentationToCreate\n )\n if (!domain) {\n throw new DcqlError('Missing domain property for creating SdJwtVc presentation.')\n }\n\n const w3cV2SdJwtCredentialService = agentContext.resolve(W3cV2SdJwtCredentialService)\n const sdJwtVc = await w3cV2SdJwtCredentialService.present(agentContext, {\n credential: presentationToCreate.credentialRecord.firstCredential.encoded,\n presentationFrame,\n })\n\n const w3cV2CredentialService = agentContext.resolve(W3cV2CredentialService)\n const w3cV2Presentation = new W3cV2Presentation({\n holder: presentationToCreate.credentialRecord.firstCredential.resolvedCredential.credentialSchemaIds[0],\n verifiableCredential: [W3cV2EnvelopedVerifiableCredential.fromVerifiableCredential(sdJwtVc)],\n })\n\n const signedPresentation = await w3cV2CredentialService.signPresentation<ClaimFormat.SdJwtW3cVp>(\n agentContext,\n {\n format: ClaimFormat.SdJwtW3cVp,\n presentation: w3cV2Presentation,\n challenge,\n domain,\n }\n )\n\n encodedCreatedPresentation = signedPresentation.encoded\n createdPresentation = signedPresentation\n } else {\n throw new DcqlError('Unsupported presentation format.')\n }\n\n if (!dcqlPresentation[credentialQueryId]) {\n dcqlPresentation[credentialQueryId] = [createdPresentation]\n } else {\n dcqlPresentation[credentialQueryId].push(createdPresentation)\n }\n\n if (!encodedDcqlPresentation[credentialQueryId]) {\n encodedDcqlPresentation[credentialQueryId] = [encodedCreatedPresentation]\n } else {\n encodedDcqlPresentation[credentialQueryId].push(encodedCreatedPresentation)\n }\n }\n }\n\n return {\n dcqlPresentation,\n encodedDcqlPresentation,\n }\n }\n\n private getPresentationFrame(\n compactSdJwt: string,\n { disclosedPaths, disclosedPayload }: { disclosedPaths?: ClaimPath[]; disclosedPayload?: JsonObject }\n ) {\n if (disclosedPaths) return buildPresentationFrameForPaths(compactSdJwt, disclosedPaths)\n // DisclosedPayload will be removed in future version\n if (disclosedPayload) return buildDisclosureFrameForPayload(disclosedPayload)\n\n throw new DcqlError(\n 'Either disclosedPaths or disclosedPayload is required to present a selectively disclosable credential.'\n )\n }\n\n private getSdJwtVcApi(agentContext: AgentContext) {\n return agentContext.dependencyManager.resolve(SdJwtVcApi)\n }\n\n private getMdocApi(agentContext: AgentContext) {\n return agentContext.dependencyManager.resolve(MdocApi)\n }\n\n private async getVerificationMethodForSubjectId(agentContext: AgentContext, subjectId: string) {\n const didsApi = agentContext.dependencyManager.resolve(DidsApi)\n\n if (!subjectId.startsWith('did:')) {\n throw new DcqlError(`Only dids are supported as credentialSubject id. ${subjectId} is not a valid did`)\n }\n\n const didDocument = await didsApi.resolveDidDocument(subjectId)\n\n if (!didDocument.authentication || didDocument.authentication.length === 0) {\n throw new DcqlError(`No authentication verificationMethods found for did ${subjectId} in did document`)\n }\n\n // the signature suite to use for the presentation is dependant on the credentials we share.\n // 1. Get the verification method for this given proof purpose in this DID document\n const [verificationMethod] = didDocument.findVerificationMethodsByPurpose(['authentication'])\n return verificationMethod\n }\n\n // FIXME: We need to take into account OpenID4VP metadata (probably providing supported/allowed algs to the DCQL create presentation method)\n private getProofTypeForLdpVc(agentContext: AgentContext, verificationMethod: VerificationMethod) {\n // For each of the supported algs, find the key types, then find the proof types\n const signatureSuiteRegistry = agentContext.dependencyManager.resolve(SignatureSuiteRegistry)\n\n const publicJwk = getPublicJwkFromVerificationMethod(verificationMethod)\n const supportedSignatureSuites = signatureSuiteRegistry.getAllByPublicJwkType(publicJwk)\n if (supportedSignatureSuites.length === 0) {\n throw new DcqlError(\n `Couldn't find a supported signature suite for the given jwk ${publicJwk.jwkTypeHumanDescription}`\n )\n }\n\n return supportedSignatureSuites[0].proofType\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiFO,IAAM,cAAN,MAAM,YAAY;;;;;CAKvB,MAAc,6BACZ,cACA,WAC0F;EAC1F,MAAM,UAAU,IAAI,IAAI,UAAU,YAAY,KAAK,MAAM,EAAE,MAAM,CAAC;EAClE,MAAM,aAA8F,CAAC;EAErG,MAAM,eAAe,UAAU,YAC5B,QAAQ,oBAAoB,gBAAgB,WAAW,UAAU,CAAC,CAClE,KAAK,MAAM,EAAE,MAAM,aAAa;EAEnC,MAAM,UAAU,KAAK,WAAW,YAAY;EAC5C,IAAI,aAAa,OAAO,YAAY,YAAY,KAAA,CAAS,GAAG;GAC1D,MAAM,cAAc,MAAM,QAAQ,eAAe,EAC/C,KAAK,aAAa,KAAK,aAAa,EACzB,QACX,EAAE,EACJ,CAAC;GACD,WAAW,KAAK,GAAG,WAAW;EAChC,OAAO,IAAI,QAAQ,IAAI,UAAU,GAAG;GAClC,MAAM,cAAc,MAAM,QAAQ,OAAO;GACzC,WAAW,KAAK,GAAG,WAAW;EAChC;EAEA,MAAM,SAAS,UAAU,YAAY,QAClC,oBACE,gBAAgB,WAAW,eAAe,EAAE,gBAAgB,QAAQ,iBAAiB,gBAAgB,SACtG,gBAAgB,WAAW,WAC/B;EAEA,MAAM,iBAAiB,OAAO,SAAS,MAAM,EAAE,MAAM,UAAU;EAE/D,MAAM,aAAa,KAAK,cAAc,YAAY;EAClD,IAAI,eAAe,OAAO,QAAQ,QAAQ,KAAA,CAAS,GAAG;GACpD,MAAM,iBAAiB,MAAM,WAAW,eAAe,EACrD,KAAK,CAEH,GAAG,eAAe,KAAK,SAAS,EAC9B,IACF,EAAE,GAEF,GAAG,eAAe,KAAK,SAAS,EAC9B,mBAAmB,CAAC,GAAG,EACzB,EAAE,CACJ,EACF,CAAC;GACD,WAAW,KAAK,GAAG,cAAc;EACnC,OAAO,IAAI,OAAO,SAAS,GAAG;GAC5B,MAAM,iBAAiB,MAAM,WAAW,OAAO;GAC/C,WAAW,KAAK,GAAG,cAAc;EACnC;EAEA,MAAM,0BAA0B,aAAa,kBAAkB,QAAQ,uBAAuB;EAC9F,IAAI,QAAQ,IAAI,aAAa,GAAG;GAC9B,MAAM,aAAa,MAAM,wBAAwB,YAAY,cAAc;IACzE,aAAA;IAGA,KAAK,UAAU,YACZ,SAAS,MAAO,EAAE,WAAW,gBAAgB,EAAE,KAAK,cAAc,CAAC,CAAE,CAAC,CACtE,KAAK,gBAAgB,EACpB,OAAO,WACT,EAAE;GACN,CAAC;GACD,WAAW,KAAK,GAAG,UAAU;EAC/B;EAEA,IAAI,QAAQ,IAAI,QAAQ,GAAG;GACzB,MAAM,aAAa,MAAM,wBAAwB,YAAY,cAAc;IACzE,aAAA;IAGA,KAAK,UAAU,YACZ,SAAS,MAAO,EAAE,WAAW,gBAAgB,EAAE,KAAK,cAAc,CAAC,CAAE,CAAC,CACtE,KAAK,gBAAgB,EACpB,eAAe,WACjB,EAAE;GACN,CAAC;GACD,WAAW,KAAK,GAAG,UAAU;EAC/B;EAOA,IALkB,UAAU,YAAY,QACrC,oBACC,gBAAgB,WAAW,eAAe,CAAC,CAAC,gBAAgB,QAAQ,iBAAiB,gBAAgB,IAG7F,CAAC,CAAC,SAAS,GAAG;GAGxB,MAAM,eAAe,MAFa,aAAa,kBAAkB,QAAQ,yBAEtB,CAAC,CAAC,YAAY,cAAc;IAC7E,aAAA;IACA,KAAK,UAAU,YACZ,SAAS,MAAO,EAAE,WAAW,eAAe,EAAE,QAAQ,iBAAiB,EAAE,OAAO,EAAE,KAAK,cAAc,CAAC,CAAE,CAAC,CACzG,KAAK,gBAAgB,EACpB,OAAO,WACT,EAAE;GACN,CAAC;GAED,WAAW,KAAK,GAAG,YAAY;EACjC;EAEA,OAAO;CACT;CAEA,0BACE,YAC6B;EAC7B,IAAI,WAAW,gBAAA,aAAqC;GAClD,MAAM,YAAa,WAAW,OAAO,KACjC,KAAK,MAAM;IACX,MAAM,SAAS,gBAAgB,uBAAuB,CAAC,CAAC,CAAC;IACzD,OAAO,SAAS,kBAAkB,YAAY,kBAAkB,QAAQ,MAAM,CAAC,IAAI,KAAA;GACrF,CAAC,CAAC,CACD,QAAQ,QAAQ,QAAQ,KAAA,CAAS;GAEpC,OAAO,aAAa,gBAAgB,SAAS,IACxC;IACC,MAAM;IACN,QAAQ;GACV,IACA,KAAA;EACN;EAEA,IAAI,WAAW,gBAAA,YAAqC;GAClD,MAAM,YAAY,WAAW,6BAC1B,KAAK,MAAM;IACV,MAAM,SAAS,gBAAgB,mBAAmB,CAAC,CAAC,CAAC;IACrD,OAAO,SAAS,kBAAkB,YAAY,kBAAkB,QAAQ,MAAM,CAAC,IAAI,KAAA;GACrF,CAAC,CAAC,CACD,QAAQ,QAAQ,QAAQ,KAAA,CAAS;GAEpC,OAAO,aAAa,gBAAgB,SAAS,IACxC;IACC,MAAM;IACN,QAAQ;GACV,IACA,KAAA;EACN;CAGF;CAEA,MAAa,gCACX,cACA,cACA,iBACyB;EAGzB,IAAI,aAAa,gBAAA,aAAqC;GACpD,MAAM,gBAAgB,gBAAgB,WAAW,cAAc,gBAAgB,MAAM,aAAa,KAAA;GAElG,IAAI,wBAAwB,CAAC,aAAa,QAAQ,GAAG;GAErD,IAAI,CAAC,eAAe,SAAS,aAAa,QAAQ,GAAG,GAAG;IACtD,MAAM,oBAAoB,MAAM,aAC7B,QAAQ,cAAc,CAAC,CACvB,kBAAkB,cAAc,cAAc;KAC7C,wBAAwB;KACxB,iCAAiC;IACnC,CAAC;IAEH,IAAI,mBACF,wBAAwB,mBAAmB;GAE/C;GAEA,OAAO;IACL,mBAAmB,gBAAgB,WAAW,cAAc,cAAc;IAC1E,WAAW,KAAK,0BAA0B,YAAY;IACtD,8BAA8B;IAC9B,KACE,sBAAsB,MAAM,yBAAyB,eAAe,SAAS,oBAAoB,CAAC,KAClG,aAAa,QAAQ;IACvB,QAAQ,aAAa;GACvB;EACF;EACA,IAAI,aAAa,gBAAA,YAAqC;GACpD,IAAI,CAAC,aAAa,eAAe,aAAa,aAAa,eAAe,UAAU,WAAW,GAC7F,MAAM,IAAI,UAAU,sDAAsD;GAG5E,OAAO;IACL,8BAA8B;IAC9B,mBAAmB;IACnB,WAAW,KAAK,0BAA0B,IAAI,KAAK,aAAa,eAAe,UAAU,EAAE,CAAC,YAAY,CAAC;IACzG,SAAS,aAAa,eAAe,UAAU,EAAE,CAAC;IAClD,YAAY,OAAO,QACjB,OAAO,YACL,aAAa,eAAe,UAAU,EAAE,CAAC,aAAa,kBAAkB,oBAAoB,CAAC,CAC/F,CACF,CAAC,CAAC,QACC,MAAM,CAAC,KAAK,YAAY;KAEvB,GAAG;MACF,MAAM,MAAM,QAEV,MAAM,UAAU;MAAE,GAAG;OAAO,KAAK,oBAAoB,KAAK;KAAa,IACxE,CAAC,CACH;IACF,IACA,CAAC,CACH;GACF;EACF;EACA,IAAI,aAAa,gBAAA,UAAmC;GAClD,MAAM,KAAK,MAAM,QAAQ,aAAa,oBAAoB,IACtD,aAAa,qBAAqB,KAClC,aAAa;GAEjB,OAAO;IACL,8BAA8B;IAC9B,mBAAmB;IACnB,WAAW,KAAK,0BAA0B,EAAE;IAC5C,QAAQ,GAAG;IACX,MAAM,GAAG;GACX;EACF;EACA,IAAI,aAAa,gBAAA,UAAmC;GAClD,MAAM,KAAK,MAAM,QAAQ,aAAa,oBAAoB,IACrD,aAAa,qBAAqB,KAClC,aAAa;GAGlB,MAAM,gBAAgB,MADa,aAAa,kBAAkB,QAAQ,0BACrB,CAAC,CAAC,8BAA8B,cAAc,EAAE;GAErG,OAAO;IACL,8BAA8B;IAC9B,mBAAmB;IACnB,WAAW,KAAK,0BAA0B,EAAE;IAC5C,QAAQ,GAAG;IACX,MAAM;GACR;EACF;EACA,IAAI,aAAa,gBAAA,aAAwC;GACvD,MAAM,aAAa,MAAM,QAAQ,aAAa,qBAAqB,oBAAoB,IACnF,aAAa,qBAAqB,qBAAqB,KACvD,aAAa,qBAAqB;GAEtC,IAAI,EAAE,sBAAsB,qCAC1B,MAAM,IAAI,UACR,6FACF;GAGF,OAAO;IACL,8BAA8B;IAC9B,mBAAmB;IACnB,WAAW,KAAK,0BAA0B,UAAU;IACpD,MAAM,QAAQ,WAAW,mBAAmB,IAAI;IAChD,QAAQ,WAAW,mBAAmB,OAAO;GAC/C;EACF;EAEA,MAAM,IAAI,UAAU,2CAA2C;CACjE;CAEA,MAAa,yBAAyB,cAA4B,WAAgD;EAChH,MAAM,oBAAoB,MAAM,KAAK,6BAA6B,cAAc,SAAS;EACzF,MAAM,wCAAkE,CAAC;EACzE,MAAM,cAAc,UAAU,MAAM,SAAS;EAE7C,MAAM,kBAAoC,kBAAkB,SAAS,WAA8C;GACjH,IAAI,OAAO,SAAS,cAAc;IAChC,sCAAsC,KAAK,MAAM;IAGjD,MAAM,OAAO,OAAO;IAEpB,OAAO;KACL,WAAW,KAAK,0BAA0B,IAAI;KAC9C,mBAAmB;KACnB,SAAS,KAAK;KACd,YAAY,KAAK;KACjB,8BAA8B;IAChC;GACF;GAEA,IAAI,OAAO,SAAS,iBAAiB;IACnC,MAAM,UAAU,OAAO;IACvB,MAAM,SAAS,QAAQ;IAKvB,sCAAsC,KACpC,QACA,QACA,GAAG,OAAO,kBAAkB,UAAU,MAAM,GAC5C,GAAG,OAAO,kBAAkB,UAAU,MAAM,CAC9C;IAEA,OAAO;KACL;MACE,WAAW,KAAK,0BAA0B,OAAO;MACjD,mBAAmB;MACnB,KAAK,OAAO,QAAQ,CAAC,CAAC;MACtB;MACA,8BAA8B;KAChC;KACA,GAAG,OAAO,kBAAkB,KACzB,sBACE;MACC,WAAW,KAAK,0BAA0B,OAAO;MACjD,mBAAmB;MACnB,KAAK;MACL;MACA,8BAA8B;KAChC,EACJ;KACA;MACE,WAAW,KAAK,0BAA0B,OAAO;MACjD,mBAAmB;MACnB,KAAK,OAAO,QAAQ,CAAC,CAAC;MACtB;MACA,8BAA8B;KAChC;KACA,GAAG,OAAO,kBAAkB,KACzB,sBACE;MACC,WAAW,KAAK,0BAA0B,OAAO;MACjD,mBAAmB;MACnB,KAAK;MACL;MACA,8BAA8B;KAChC,EACJ;IACF;GACF;GAEA,IAAI,OAAO,SAAS,uBAAuB;IACzC,MAAM,kBAAkB,OAAO;IAC/B,sCAAsC,KAAK,MAAM;IACjD,IAAI,gBAAgB,gBAAA,UAClB,OAAO;KACL,mBAAmB;KACnB,WAAW,KAAK,0BAA0B,eAAe;KACzD,MAAM,OAAO,QAAQ,CAAC,CAAC,iBAAiB,CAAC;KACzC,QAAQ,gBAAgB;KACxB,8BAA8B;IAChC;IAGF,OAAO;KACL,mBAAmB;KACnB,WAAW,KAAK,0BAA0B,eAAe;KACzD,MAAM,gBAAgB;KACtB,QAAQ,gBAAgB;KACxB,8BAA8B;IAChC;GACF;GAEA,IAAI,OAAO,SAAS,yBAAyB;IAC3C,sCAAsC,KAAK,MAAM;IACjD,MAAM,kBAAkB,OAAO;IAE/B,OAAO;KACL,mBAAmB;KACnB,WAAW,KAAK,0BAA0B,eAAe;KACzD,MAAM,QAAQ,gBAAgB,mBAAmB,IAAI;KACrD,QAAQ,gBAAgB,mBAAmB,OAAO;KAClD,8BAA8B;IAChC;GACF;GAEA,MAAM,IAAI,UAAU,yBAAyB;EAC/C,CAAC;EAED,MAAM,cAAc,UAAU,MAAM,aAAa,eAAe;EAEhE,MAAM,oBAAoB,OAAO,YAC/B,OAAO,QAAQ,YAAY,kBAAkB,CAAC,CAAC,KAAK,CAAC,qBAAqB,YAAY;GACpF,MAAM,oBAAoB,OAAO,qBAC7B,iBAAiB,OAAO,qBAAqB,eAAe;IAC1D,MAAM,SAAS,sCAAsC,WAAW;IAehE,OAAO;KAbL,GAAG;KACH;KACA,QAAQ,WAAW,OAAO,UACtB;MACE,GAAG,WAAW;MACd,SAAS;MACT,kBAAkB,iBAAiB,WAAW,OAAO,mBAAmB,cAAc;OACpF,GAAG;OACH,GAAG,KAAK,2BAA2B,QAAQ,UAAU,aAAa,mBAAmB;MACvF,EAAE;KACJ,IACA,WAAW;IAEM;GACzB,CAAC,IACD,KAAA;GAGJ,IAAI,CAAC,OAAO,SACV,OAAO,CACL,qBACA;IACE,GAAG;IACH,oBAAoB;GACtB,CACF;GAGF,OAAO,CACL,qBACA;IACE,GAAG;IACH,oBAAoB;IACpB,mBAAmB,iBAAiB,OAAO,oBAAoB,eAAe;KAC5E,MAAM,SAAS,sCAAsC,WAAW;KAYhE,OAAO;MAVL,GAAG;MACH;MACA,QAAQ;OACN,GAAG,WAAW;OACd,kBAAkB,iBAAiB,WAAW,OAAO,mBAAmB,cAAc;QACpF,GAAG;QACH,GAAG,KAAK,2BAA2B,QAAQ,UAAU,aAAa,mBAAmB;OACvF,EAAE;MACJ;KAEqB;IACzB,CAAC;GACH,CACF;EACF,CAAC,CACH;EAEA,OAAO;GACL,GAAG;GACH,oBAAoB;EACtB;CACF;;;;;;;;;;;CAYA,2BACE,QACA,UACA,WACA,mBACA;EAEA,MAAM,sBAAsB;GAC1B,MAAM,gBAAgB,UAAU,YAAY,MAAM,eAAe,WAAW,OAAO,iBAAiB,CAAC,EAAE;GACvG,MAAM,oBAAoB,SAAS,uBAAuB,CAAC,EAAA,CAAG,SAAS,UAAU;IAC/E,MAAM,cAAc,gBAAgB;IAGpC,OAAO,eAAe,UAAU,cAAc,CAAC,YAAY,IAAI,IAAI,CAAC;GACtE,CAAC;GAED,OAAO,6BAA6B,kBAAkB,SAAS,MAAM;EACvE;EAEA,IAAI,OAAO,SAAS,iBAAiB;GACnC,MAAM,EAAE,cAAc,mBAAmB,yBAAyB,OAAO,SAAS,cAAc,CAAC;GAEjG,OAAO;IAAE,QAAQ;IAA8C,iBAAiB;GAAe;EACjG;EAEA,IAAI,OAAO,SAAS,2BAA2B,OAAO,2BAA2B,gCAAgC;GAC/G,MAAM,EAAE,cAAc,mBAAmB,yBAAyB,OAAO,gBAAgB,SAAS,cAAc,CAAC;GAEjH,OAAO;IAEL,QAAQ,gBAAgB,SAAS,cAAc,iBAAiB,EAAE,UAAU,MAAM,CAAC,CAAC,CAAC,OAAO;IAG5F,iBAAiB;GACnB;EACF;EAEA,OAAO,CAAC;CACV;CAEA,MAAa,4BACX,cACA,kBACA,WACA;EACA,MAAM,2BAA2B,OAAO,YACtC,MAAM,QAAQ,IACZ,OAAO,QAAQ,gBAAgB,CAAC,CAAC,IAAI,OAAO,CAAC,cAAc,mBAAmB;GAC5E,MAAM,kBAAkB,UAAU,YAAY,MAAM,MAAM,EAAE,OAAO,YAAY;GAC/E,IAAI,CAAC,iBACH,MAAM,IAAI,UACR,oEAAoE,aAAa,gDACnF;GAGF,OAAO,CACL,cACA,MAAM,QAAQ,IACZ,cAAc,KAAK,iBACjB,KAAK,gCAAgC,cAAc,cAAc,eAAe,CAClF,CACF,CACF;EACF,CAAC,CACH,CACF;EAEA,MAAM,qBAAqB,uBAAuB,qBAAqB,0BAA0B,EAAE,UAAU,CAAC;EAE9G,IAAI,CAAC,mBAAmB,kBACtB,MAAM,IAAI,UAAU,gDAAgD,EAClE,oBAAoB,OAAO,QAAQ,mBAAmB,sBAAsB,CAAC,CAAC,CAAC,CAC5E,SAAS,CAAC,SAAS,WAClB,MAAM,UACF,KAAA,IACA,CAAC,MAAM,qBACL,qCAAqC,QAAQ,+BAC7C,MAAM,mBAAmB,KACtB,qBACC,yBAAyB,iBAAiB,uBAAuB,oCAAoC,QAAQ,KAAK,KAAK,UACrH;GACE,GAAI,iBAAiB,OAAO,UACxB,CAAC,IACD,EAAE,QAAQ,iBAAiB,OAAO,kBAAkB,KAAK,OAAO,GAAG,MAAM,EAAE;GAC/E,GAAI,iBAAiB,oBAAoB,UACrC,CAAC,IACD,EACE,qBACE,iBAAiB,oBAAoB,2BAA2B,KAC7D,OAAO,GAAG,MACb,EACJ;GACJ,GAAI,iBAAiB,KAAK,UAAU,CAAC,IAAI,EAAE,MAAM,iBAAiB,KAAK,OAAO;EAChF,GACA,MACA,CACF,GACJ,CACR,CAAC,CACA,QAAQ,YAAY,YAAY,KAAA,CAAS,EAC9C,CAAC;EAGH,OAAO;CACT;CAEA,uBAA+B,iBAA+D;EAC5F,MAAM,CAAC,EAAE,QAAQ,qBAAqB,gBAAgB,OAAO;EAE7D,OAAO,kBACH;GAAE,gBAAgB;GAAiB,kBAAkB;EAAqB,IAC1E,EAAE,kBAAkB,OAAqB;CAC/C;CAEA,2CAAmD,iBAAsC;EACvF,IAAI,gBAAgB,OAAO,SAAS,cAClC,OAAO;GACL,aAAA;GACA,kBAAkB,gBAAgB;GAClC,kBAAkB,gBAAgB,OAAO,iBAAiB,EAAE,CAAC;EAC/D;EAEF,IAAI,gBAAgB,OAAO,SAAS,iBAClC,OAAO;GACL,aAAA;GACA,kBAAkB,gBAAgB;GAClC,GAAG,KAAK,uBAAuB,eAAe;EAChD;EAGF,IAAI,gBAAgB,OAAO,SAAS,uBAClC,OAAO;GACL,aAAa,gBAAgB,OAAO,gBAAgB;GACpD,kBAAkB,gBAAgB;GAClC,kBAAkB,gBAAgB,OAAO,gBAAgB;EAC3D;EAGF,IAAI,gBAAgB,OAAO,SAAS,yBAAyB;GAC3D,MAAM,cAAc,gBAAgB,OAAO,gBAAgB;GAE3D,IAAI,gBAAA,SACF,MAAM,IAAI,UAAU,kFAAkF;GAGxG,IAAI,gBAAA,aACF,OAAO;IACL;IACA,kBAAkB,gBAAgB;IAClC,GAAG,KAAK,uBAAuB,eAAe;GAChD;GAGF,OAAO;IACL;IACA,kBAAkB,gBAAgB;IAClC,kBAAkB,gBAAgB,OAAO,iBAAiB,EAAE,CAAC;GAC/D;EACF;EAEA,MAAM,IAAI,UAAU,kCAAkC;CACxD;;;;;CAMA,4BACE,iBACA,EAAE,UAAA,iBAAgG,CAAC,GACxE;EAC3B,IAAI,CAAC,gBAAgB,kBACnB,MAAM,IAAI,UACR,kGACF;EAGF,MAAM,cAAyC,CAAC;EAEhD,IAAI,gBAAgB,iBAClB,mBAAmB,KAAK,MAAM,iBAAiB,gBAAgB,iBAAiB;GAE9E,IAAI,cAAc,aAAa,OAAO;GACtC,MAAM,sBAAsB,cAAc;GAE1C,IAAI,CAAC,qBACH,MAAM,IAAI,UAAU,sDAAsD;GAG5E,KAAK,MAAM,sBAAsB,qBAAqB;IACpD,MAAM,gBAAgB,mBAAmB,KAAK,sBAAsB;KAClE,MAAM,kBAAkB,gBAAgB,mBAAmB;KAC3D,IAAI,CAAC,gBAAgB,SAAS,OAAO,KAAA;KACrC,MAAM,QAAQ,gBAAgB,kBAAkB,MAAM,UACpD,mCAAmC;MAAE,kBAAkB,MAAM;MAAQ;KAAQ,CAAC,CAChF;KAEA,IAAI,CAAC,OAAO,OAAO,KAAA;KACnB,OAAO;MACL;MACA;KACF;IACF,CAAC;IAED,IAAI,cAAc,OAAO,MAAM,MAAM,KAAA,CAAS,GAAG;KAC/C,KAAK,MAAM,EAAE,OAAO,uBAAuB,eACzC,YAAY,qBAAqB,CAAC,KAAK,2CAA2C,KAAK,CAAC;KAG1F,SAAS;IACX;GACF;GAEA,MAAM,IAAI,UACR,4HACF;EACF;OAEA,KAAK,MAAM,mBAAmB,gBAAgB,aAAa;GACzD,MAAM,kBAAkB,gBAAgB,mBAAmB,gBAAgB;GAC3E,IAAI,CAAC,gBAAgB,SACnB,MAAM,IAAI,UACR,sDAAsD,gBAAgB,GAAG,kCAC3E;GAGF,MAAM,aAAa,gBAAgB,kBAAkB,MAAM,UACzD,mCAAmC;IAAE,kBAAkB,MAAM;IAAQ;GAAQ,CAAC,CAChF;GACA,IAAI,CAAC,YACH,MAAM,IAAI,UACR,wDAAwD,gBAAgB,GAAG,6EAC7E;GAGF,YAAY,gBAAgB,MAAM,CAAC,KAAK,2CAA2C,UAAU,CAAC;EAChG;EAGF,OAAO;CACT;CAEA,kBAAyB,WAA6D;EACpF,MAAM,SAAS,UAAU,MAAM,SAAsB;EACrD,UAAU,SAAS,MAAM;EACzB,OAAO;CACT;CAEA,MAAa,mBACX,cACA,SASC;EACD,MAAM,EAAE,QAAQ,WAAW,0BAA0B;EAErD,MAAM,mBAAqC,CAAC;EAC5C,MAAM,0BAAoD,CAAC;EAC3D,MAAM,0BAA0BA,6BAA+B,QAAQ,2BAA2B;EAElG,KAAK,MAAM,CAAC,mBAAmB,0BAA0B,OAAO,QAAQ,uBAAuB,GAC7F,KAAK,MAAM,wBAAwB,uBAAuB;GACxD,IAAI;GACJ,IAAI;GAEJ,IAAI,qBAAqB,gBAAA,YAAqC;IAC5D,MAAM,aAAa,qBAAqB;IACxC,IAAI,CAAC,uBACH,MAAM,IAAI,UAAU,yEAAyE;IAG/F,MAAM,EAAE,uBAAuB,MAAM,gCAAgC;KACnE;KACA,SAAS,qBAAqB;KAC9B,kBAAkB;IACpB,CAAC;IAiBD,MAAM,2BAA0B,MAfH,mBAAmB,qBAAqB,cAAc;KACjF,OAAO,CAAC,kBAAkB;KAC1B,kBAAkB,CAChB;MACE,SAAS,WAAW,QAAQ,CAAC,CAAC;MAC9B,YAAY,OAAO,YACjB,OAAO,QAAQ,qBAAqB,gBAAgB,CAAC,CAAC,KAAK,CAAC,KAAK,WAAW;OAE1E,OAAO,CAAC,KAAK,OAAO,YAAY,OAAO,QAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC;MACrF,CAAC,CACH;KACF,CACF;KACA,0BAA0B;IAC5B,CAAC,EAAA,CAC8C;IAE/C,6BAA6B;IAC7B,sBAAsB,mBAAmB,cAAc,uBAAuB;GAChF,OAAO,IAAI,qBAAqB,gBAAA,aAAqC;IACnE,IAAI,CAAC,QACH,MAAM,IAAI,UAAU,4DAA4D;IAGlF,MAAM,EAAE,uBAAuB,MAAM,gCAAgC;KACnE;KACA,SAAS,qBAAqB;KAC9B,kBAAkB,qBAAqB;IACzC,CAAC;IAED,MAAM,oBAAoB,KAAK,qBAC7B,OAAO,uBAAuB,WAAW,qBAAqB,mBAAmB,SACjF,oBACF;IAEA,MAAM,aAAa,KAAK,cAAc,YAAY;IAClD,MAAM,eAAe,MAAM,WAAW,QAAQ;KAC5C,SAAS;KACT;KACA,kBAAkB;MAChB,UAAU;MACV,OAAO;MACP,UAAU,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;KACxC;KACA,mBAAmB,qBAAqB;IAC1C,CAAC;IAED,6BAA6B;IAC7B,sBAAsB,WAAW,YAAY,YAAY;GAC3D,OAAO,IAAI,qBAAqB,gBAAA,UAAmC;IACjE,MAAM,EAAE,uBAAuB,MAAM,gCAAgC;KACnE;KACA,SAAS,qBAAqB;KAC9B,kBAAkB,qBAAqB;IACzC,CAAC;IAED,IAAI,CAAC,mBAAmB,qBAAqB,IAC3C,MAAM,IAAI,UAAU,+DAA+D;IAIrF,MAAM,qBAAqB,MAAM,KAAK,kCACpC,cACA,mBAAmB,qBAAqB,EAC1C;IAEA,MAAM,uBAAuB,aAAa,QAAQ,oBAAoB;IACtE,MAAM,kBAAkB,IAAI,gBAAgB;KAC1C,sBAAsB,CAAC,kBAAkB;KACzC,QAAQ,mBAAmB;IAC7B,CAAC;IAED,MAAM,YAAY,mCAAmC,kBAAkB;IAEvE,MAAM,qBAAqB,MAAM,qBAAqB,iBAAoC,cAAc;KACtG,QAAA;KACA,KAAK,UAAU;KACf,oBAAoB,mBAAmB;KACvC,cAAc;KACd;KACA;IACF,CAAC;IAED,6BAA6B,mBAAmB;IAChD,sBAAsB;GACxB,OAAO,IAAI,qBAAqB,gBAAA,UAAmC;IACjE,MAAM,EAAE,uBAAuB,MAAM,gCAAgC;KACnE;KACA,SAAS,qBAAqB;KAC9B,kBAAkB,qBAAqB;IACzC,CAAC;IAED,IAAI,CAAC,mBAAmB,qBAAqB,IAC3C,MAAM,IAAI,UAAU,+DAA+D;IAIrF,MAAM,qBAAqB,MAAM,KAAK,kCACpC,cACA,mBAAmB,qBAAqB,EAC1C;IAEA,MAAM,uBAAuB,aAAa,QAAQ,oBAAoB;IACtE,MAAM,kBAAkB,IAAI,gBAAgB;KAC1C,sBAAsB,CAAC,kBAAkB;KACzC,QAAQ,mBAAmB;IAC7B,CAAC;IAED,MAAM,qBAAqB,MAAM,qBAAqB,iBAAiB,cAAc;KACnF,QAAA;KAIA,WAAW,KAAK,qBAAqB,cAAc,kBAAkB;KACrE,cAAc,IAAI,SAAS,2BAA2B;MAAE;MAAW;KAAO,CAAC;KAC3E,oBAAoB,mBAAmB;KACvC,cAAc;KACd;KACA;IACF,CAAC;IAED,6BAA6B,mBAAmB;IAChD,sBAAsB;GACxB,OAAO,IAAI,qBAAqB,gBAAA,UAAsC;IACpE,MAAM,yBAAyB,aAAa,QAAQ,sBAAsB;IAC1E,MAAM,kBAAkB,qBAAqB,iBAAiB;IAE9D,IAAI,gBAAgB,gBAAA,SAClB,MAAM,IAAI,UAAU,iFAAiF;IAGvG,MAAM,oBAAoB,IAAI,kBAAkB;KAC9C,QAAQ,gBAAgB,mBAAmB,qBAAqB;KAChE,sBAAsB,CAAC,mCAAmC,yBAAyB,eAAe,CAAC;IACrG,CAAC;IAED,MAAM,qBAAqB,MAAM,uBAAuB,iBAAuC,cAAc;KAC3G,QAAA;KACA,cAAc;KACd;KACA;IACF,CAAC;IAED,6BAA6B,mBAAmB;IAChD,sBAAsB;GACxB,OAAO,IAAI,qBAAqB,gBAAA,aAAwC;IACtE,MAAM,oBAAoB,KAAK,qBAC7B,qBAAqB,iBAAiB,gBAAgB,SACtD,oBACF;IACA,IAAI,CAAC,QACH,MAAM,IAAI,UAAU,4DAA4D;IAIlF,MAAM,UAAU,MADoB,aAAa,QAAQ,2BACT,CAAC,CAAC,QAAQ,cAAc;KACtE,YAAY,qBAAqB,iBAAiB,gBAAgB;KAClE;IACF,CAAC;IAED,MAAM,yBAAyB,aAAa,QAAQ,sBAAsB;IAC1E,MAAM,oBAAoB,IAAI,kBAAkB;KAC9C,QAAQ,qBAAqB,iBAAiB,gBAAgB,mBAAmB,oBAAoB;KACrG,sBAAsB,CAAC,mCAAmC,yBAAyB,OAAO,CAAC;IAC7F,CAAC;IAED,MAAM,qBAAqB,MAAM,uBAAuB,iBACtD,cACA;KACE,QAAA;KACA,cAAc;KACd;KACA;IACF,CACF;IAEA,6BAA6B,mBAAmB;IAChD,sBAAsB;GACxB,OACE,MAAM,IAAI,UAAU,kCAAkC;GAGxD,IAAI,CAAC,iBAAiB,oBACpB,iBAAiB,qBAAqB,CAAC,mBAAmB;QAE1D,iBAAiB,kBAAkB,CAAC,KAAK,mBAAmB;GAG9D,IAAI,CAAC,wBAAwB,oBAC3B,wBAAwB,qBAAqB,CAAC,0BAA0B;QAExE,wBAAwB,kBAAkB,CAAC,KAAK,0BAA0B;EAE9E;EAGF,OAAO;GACL;GACA;EACF;CACF;CAEA,qBACE,cACA,EAAE,gBAAgB,oBAClB;EACA,IAAI,gBAAgB,OAAO,+BAA+B,cAAc,cAAc;EAEtF,IAAI,kBAAkB,OAAO,+BAA+B,gBAAgB;EAE5E,MAAM,IAAI,UACR,wGACF;CACF;CAEA,cAAsB,cAA4B;EAChD,OAAO,aAAa,kBAAkB,QAAQ,UAAU;CAC1D;CAEA,WAAmB,cAA4B;EAC7C,OAAO,aAAa,kBAAkB,QAAQ,OAAO;CACvD;CAEA,MAAc,kCAAkC,cAA4B,WAAmB;EAC7F,MAAM,UAAU,aAAa,kBAAkB,QAAQ,OAAO;EAE9D,IAAI,CAAC,UAAU,WAAW,MAAM,GAC9B,MAAM,IAAI,UAAU,oDAAoD,UAAU,oBAAoB;EAGxG,MAAM,cAAc,MAAM,QAAQ,mBAAmB,SAAS;EAE9D,IAAI,CAAC,YAAY,kBAAkB,YAAY,eAAe,WAAW,GACvE,MAAM,IAAI,UAAU,uDAAuD,UAAU,iBAAiB;EAKxG,MAAM,CAAC,sBAAsB,YAAY,iCAAiC,CAAC,gBAAgB,CAAC;EAC5F,OAAO;CACT;CAGA,qBAA6B,cAA4B,oBAAwC;EAE/F,MAAM,yBAAyB,aAAa,kBAAkB,QAAQ,sBAAsB;EAE5F,MAAM,YAAY,mCAAmC,kBAAkB;EACvE,MAAM,2BAA2B,uBAAuB,sBAAsB,SAAS;EACvF,IAAI,yBAAyB,WAAW,GACtC,MAAM,IAAI,UACR,+DAA+D,UAAU,yBAC3E;EAGF,OAAO,yBAAyB,EAAE,CAAC;CACrC;AACF;AA/9BC,cAAA,WAAA,CAAA,WAAW,CAAA,GAAA,WAAA"}
1
+ {"version":3,"file":"DcqlService.mjs","names":["getDcqlVcPresentationsToCreate"],"sources":["../../../src/modules/dcql/DcqlService.ts"],"sourcesContent":["import {\n DcqlCredential,\n DcqlCredentialQuery,\n DcqlMdocCredential,\n DcqlPresentationResult,\n DcqlQuery,\n DcqlSdJwtVcCredential,\n DcqlW3cVcCredential,\n} from 'dcql'\nimport type { AgentContext } from '../../agent'\nimport { injectable } from '../../plugins'\nimport { isNonEmptyArray, type JsonObject, type JsonValue, mapNonEmptyArray } from '../../types'\nimport { asArray, JsonTransformer, TypedArrayEncoder } from '../../utils'\nimport {\n CredentialMultiInstanceUseMode,\n canUseInstanceFromCredentialRecord,\n useInstanceFromCredentialRecord,\n} from '../../utils/credentialUse'\nimport { DidsApi, getPublicJwkFromVerificationMethod, VerificationMethod } from '../dids'\nimport type { VerifiableCredential, VerifiablePresentation } from '../dif-presentation-exchange/index'\nimport {\n Mdoc,\n MdocApi,\n MdocDeviceResponse,\n type MdocNameSpaces,\n MdocRecord,\n type MdocSessionTranscriptOptions,\n} from '../mdoc'\nimport { SdJwtVcApi, SdJwtVcRecord, SdJwtVcService } from '../sd-jwt-vc'\nimport {\n applyDisclosuresForPaths,\n buildDisclosureFrameForPayload,\n buildPresentationFrameForPaths,\n type ClaimPath,\n getClaimPathsForDcqlClaimSet,\n} from '../sd-jwt-vc/disclosureFrame'\nimport {\n ClaimFormat,\n SignatureSuiteRegistry,\n W3cCredentialRecord,\n W3cCredentialRepository,\n W3cCredentialService,\n W3cJsonLdCredentialService,\n W3cJsonLdVerifiableCredential,\n W3cPresentation,\n W3cV2Credential,\n W3cV2CredentialRecord,\n W3cV2CredentialRepository,\n W3cV2CredentialService,\n W3cV2EnvelopedVerifiableCredential,\n W3cV2JwtVerifiableCredential,\n W3cV2Presentation,\n type W3cV2VerifiableCredential,\n} from '../vc'\nimport { purposes } from '../vc/linked-data-proofs/adapters/jsonld-signatures-adapter'\nimport { W3cV2SdJwtCredentialService, W3cV2SdJwtVerifiableCredential } from '../vc/sd-jwt-vc'\nimport { X509Certificate } from '../x509'\nimport { DcqlError } from './DcqlError'\nimport type {\n DcqlCredentialsForRequest,\n DcqlEncodedPresentations,\n DcqlFailedCredential,\n DcqlPresentation,\n DcqlQueryResult,\n DcqlSelectiveDisclosure,\n DcqlValidCredential,\n} from './models'\nimport { dcqlGetPresentationsToCreate as getDcqlVcPresentationsToCreate } from './utils'\n\nexport interface DcqlSelectCredentialsForRequestOptions {\n /**\n * The usage mode to apply to the credentials when selecting credentials.\n *\n * If an usage mode is selected that require a new instance to be used, and there's no\n * new instances available, an error will be thrown.\n *\n * It does not actually select the credential from the record yet, it just filters\n * out records that don't match the filter.\n */\n useMode?: CredentialMultiInstanceUseMode\n}\n\n@injectable()\nexport class DcqlService {\n /**\n * Queries the wallet for credentials that match the given dcql query. This only does an initial query based on the\n * schema of the input descriptors. It does not do any further filtering based on the constraints in the input descriptors.\n */\n private async queryCredentialsForDcqlQuery(\n agentContext: AgentContext,\n dcqlQuery: DcqlQuery\n ): Promise<Array<SdJwtVcRecord | W3cCredentialRecord | W3cV2CredentialRecord | MdocRecord>> {\n const formats = new Set(dcqlQuery.credentials.map((c) => c.format))\n const allRecords: Array<SdJwtVcRecord | W3cCredentialRecord | W3cV2CredentialRecord | MdocRecord> = []\n\n const mdocDoctypes = dcqlQuery.credentials\n .filter((credentialQuery) => credentialQuery.format === 'mso_mdoc')\n .map((c) => c.meta?.doctype_value)\n\n const mdocApi = this.getMdocApi(agentContext)\n if (mdocDoctypes.every((doctype) => doctype !== undefined)) {\n const mdocRecords = await mdocApi.findAllByQuery({\n $or: mdocDoctypes.map((docType) => ({\n docType: docType,\n })),\n })\n allRecords.push(...mdocRecords)\n } else if (formats.has('mso_mdoc')) {\n const mdocRecords = await mdocApi.getAll()\n allRecords.push(...mdocRecords)\n }\n\n const sdJwts = dcqlQuery.credentials.filter(\n (credentialQuery): credentialQuery is DcqlCredentialQuery.SdJwtVc =>\n (credentialQuery.format === 'vc+sd-jwt' && !(credentialQuery.meta && 'type_values' in credentialQuery.meta)) ||\n credentialQuery.format === 'dc+sd-jwt'\n )\n\n const sdJwtVctValues = sdJwts.flatMap((c) => c.meta?.vct_values)\n\n const sdJwtVcApi = this.getSdJwtVcApi(agentContext)\n if (sdJwtVctValues.every((vct) => vct !== undefined)) {\n const sdjwtVcRecords = await sdJwtVcApi.findAllByQuery({\n $or: [\n // Look for direct vct match\n ...sdJwtVctValues.map((vct) => ({\n vct,\n })),\n // Or an extended vct value\n ...sdJwtVctValues.map((vct) => ({\n extendedVctValues: [vct],\n })),\n ],\n })\n allRecords.push(...sdjwtVcRecords)\n } else if (sdJwts.length > 0) {\n const sdJwtVcRecords = await sdJwtVcApi.getAll()\n allRecords.push(...sdJwtVcRecords)\n }\n\n const w3cCredentialRepository = agentContext.dependencyManager.resolve(W3cCredentialRepository)\n if (formats.has('jwt_vc_json')) {\n const w3cRecords = await w3cCredentialRepository.findByQuery(agentContext, {\n claimFormat: ClaimFormat.JwtVc,\n\n // For jwt_vc_json we query the non-expanded types\n $or: dcqlQuery.credentials\n .flatMap((c) => (c.format === 'jwt_vc_json' ? c.meta.type_values : []))\n .map((typeValues) => ({\n types: typeValues,\n })),\n })\n allRecords.push(...w3cRecords)\n }\n\n if (formats.has('ldp_vc')) {\n const w3cRecords = await w3cCredentialRepository.findByQuery(agentContext, {\n claimFormat: ClaimFormat.LdpVc,\n\n // For LDP_VC we query the expanded types\n $or: dcqlQuery.credentials\n .flatMap((c) => (c.format === 'jwt_vc_json' ? c.meta.type_values : []))\n .map((typeValues) => ({\n expandedTypes: typeValues,\n })),\n })\n allRecords.push(...w3cRecords)\n }\n\n const w3cSdJwts = dcqlQuery.credentials.filter(\n (credentialQuery): credentialQuery is DcqlCredentialQuery.W3cVc & { format: 'vc+sd-jwt' } =>\n credentialQuery.format === 'vc+sd-jwt' && !!credentialQuery.meta && 'type_values' in credentialQuery.meta\n )\n\n if (w3cSdJwts.length > 0) {\n const w3cV2CredentialRepository = agentContext.dependencyManager.resolve(W3cV2CredentialRepository)\n\n const w3cV2Records = await w3cV2CredentialRepository.findByQuery(agentContext, {\n claimFormat: ClaimFormat.SdJwtW3cVc,\n $or: dcqlQuery.credentials\n .flatMap((c) => (c.format === 'vc+sd-jwt' && c.meta && 'type_values' in c.meta ? c.meta.type_values : []))\n .map((typeValues) => ({\n types: typeValues,\n })),\n })\n\n allRecords.push(...w3cV2Records)\n }\n\n return allRecords\n }\n\n private getAuthorityForCredential(\n credential: VerifiableCredential | W3cV2EnvelopedVerifiableCredential\n ): DcqlCredential['authority'] {\n if (credential.claimFormat === ClaimFormat.SdJwtDc) {\n const akiValues = (credential.header.x5c as string[] | undefined)\n ?.map((c) => {\n const akiHex = X509Certificate.fromEncodedCertificate(c).authorityKeyIdentifier\n return akiHex ? TypedArrayEncoder.toBase64Url(TypedArrayEncoder.fromHex(akiHex)) : undefined\n })\n .filter((aki) => aki !== undefined)\n\n return akiValues && isNonEmptyArray(akiValues)\n ? ({\n type: 'aki',\n values: akiValues,\n } as const)\n : undefined\n }\n\n if (credential.claimFormat === ClaimFormat.MsoMdoc) {\n const akiValues = credential.issuerSignedCertificateChain\n .map((c) => {\n const akiHex = X509Certificate.fromRawCertificate(c).authorityKeyIdentifier\n return akiHex ? TypedArrayEncoder.toBase64Url(TypedArrayEncoder.fromHex(akiHex)) : undefined\n })\n .filter((aki) => aki !== undefined)\n\n return akiValues && isNonEmptyArray(akiValues)\n ? ({\n type: 'aki',\n values: akiValues,\n } as const)\n : undefined\n }\n\n return undefined\n }\n\n public async getDcqlCredentialRepresentation(\n agentContext: AgentContext,\n presentation: VerifiablePresentation,\n queryCredential: DcqlQuery['credentials'][number]\n ): Promise<DcqlCredential> {\n // SD-JWT credential can be used as both dc+sd-jwt and vc+sd-jwt\n // At some point we might want to look at the header value of the sd-jwt (vc+sd-jwt vc dc+sd-jwt)\n if (presentation.claimFormat === ClaimFormat.SdJwtDc) {\n const requestedVcts = queryCredential.format === 'dc+sd-jwt' ? queryCredential.meta?.vct_values : undefined\n\n let presentationVctValues = [presentation.payload.vct]\n // FIXME: we should probably add an option whether to resolve VCT if we didn't get a direct hit\n if (!requestedVcts?.includes(presentation.payload.vct)) {\n const typeMetadataChain = await agentContext\n .resolve(SdJwtVcService)\n .fetchTypeMetadata(agentContext, presentation, {\n throwErrorOnFetchError: false,\n throwErrorOnUnsupportedVctValue: false,\n })\n\n if (typeMetadataChain) {\n presentationVctValues = typeMetadataChain?.vctValues\n }\n }\n\n return {\n credential_format: queryCredential.format === 'dc+sd-jwt' ? 'dc+sd-jwt' : 'vc+sd-jwt',\n authority: this.getAuthorityForCredential(presentation),\n cryptographic_holder_binding: presentation.kbJwt !== undefined,\n vct:\n presentationVctValues.find((presentationVctValue) => requestedVcts?.includes(presentationVctValue)) ??\n presentation.payload.vct,\n claims: presentation.prettyClaims as DcqlSdJwtVcCredential.Claims,\n } satisfies DcqlSdJwtVcCredential\n }\n if (presentation.claimFormat === ClaimFormat.MsoMdoc) {\n if (!presentation.deviceResponse.documents || presentation.deviceResponse.documents.length !== 1) {\n throw new DcqlError('MDOC presentations must contain exactly one document')\n }\n\n return {\n cryptographic_holder_binding: true,\n credential_format: 'mso_mdoc',\n authority: this.getAuthorityForCredential(new Mdoc(presentation.deviceResponse.documents[0].issuerSigned)),\n doctype: presentation.deviceResponse.documents[0].docType,\n namespaces: Object.entries(\n Object.fromEntries(\n presentation.deviceResponse.documents[0].issuerSigned.issuerNamespaces?.issuerNamespaces ?? []\n )\n ).reduce(\n (prev, [key, value]) => ({\n // biome-ignore lint/performance/noAccumulatingSpread: time complexity not relevant here\n ...prev,\n [key]: value.reduce<Record<string, unknown>>(\n // biome-ignore lint/performance/noAccumulatingSpread: time complexity not relevant here\n (prev, curr) => ({ ...prev, [curr.elementIdentifier]: curr.elementValue }),\n {}\n ),\n }),\n {}\n ),\n } satisfies DcqlMdocCredential\n }\n if (presentation.claimFormat === ClaimFormat.JwtVp) {\n const vc = Array.isArray(presentation.verifiableCredential)\n ? presentation.verifiableCredential[0]\n : presentation.verifiableCredential\n\n return {\n cryptographic_holder_binding: hasHolderBinding(undefined, vc.credentialSubjectIds),\n credential_format: 'jwt_vc_json',\n authority: this.getAuthorityForCredential(vc),\n claims: vc.jsonCredential as { [key: string]: JsonValue },\n type: vc.type,\n } satisfies DcqlW3cVcCredential\n }\n if (presentation.claimFormat === ClaimFormat.LdpVp) {\n const vc = Array.isArray(presentation.verifiableCredential)\n ? (presentation.verifiableCredential[0] as W3cJsonLdVerifiableCredential)\n : (presentation.verifiableCredential as W3cJsonLdVerifiableCredential)\n\n const w3cJsonLdCredentialService = agentContext.dependencyManager.resolve(W3cJsonLdCredentialService)\n const expandedTypes = await w3cJsonLdCredentialService.getExpandedTypesForCredential(agentContext, vc)\n\n return {\n cryptographic_holder_binding: hasHolderBinding(undefined, vc.credentialSubjectIds),\n credential_format: 'ldp_vc',\n authority: this.getAuthorityForCredential(vc),\n claims: vc.jsonCredential as DcqlW3cVcCredential.Claims,\n type: expandedTypes,\n } satisfies DcqlW3cVcCredential\n }\n if (presentation.claimFormat === ClaimFormat.SdJwtW3cVp) {\n const firstEntry = Array.isArray(presentation.resolvedPresentation.verifiableCredential)\n ? presentation.resolvedPresentation.verifiableCredential[0]\n : presentation.resolvedPresentation.verifiableCredential\n\n if (!(firstEntry instanceof W3cV2EnvelopedVerifiableCredential)) {\n throw new DcqlError(\n 'Expected an EnvelopedVerifiableCredential entry for vc+sd-jwt presentation claim extraction'\n )\n }\n\n return {\n cryptographic_holder_binding: hasW3cV2HolderBinding(firstEntry.envelopedCredential),\n credential_format: 'vc+sd-jwt',\n authority: this.getAuthorityForCredential(firstEntry),\n type: asArray(firstEntry.resolvedCredential.type),\n claims: firstEntry.resolvedCredential.toJSON() as { [key: string]: JsonValue },\n } satisfies DcqlW3cVcCredential\n }\n\n throw new DcqlError('Unsupported claim format for presentation')\n }\n\n public async getCredentialsForRequest(agentContext: AgentContext, dcqlQuery: DcqlQuery): Promise<DcqlQueryResult> {\n const credentialRecords = await this.queryCredentialsForDcqlQuery(agentContext, dcqlQuery)\n const credentialRecordsWithFormatDuplicates: typeof credentialRecords = []\n const parsedQuery = DcqlQuery.parse(dcqlQuery)\n\n const dcqlCredentials: DcqlCredential[] = credentialRecords.flatMap((record): DcqlCredential | DcqlCredential[] => {\n if (record.type === 'MdocRecord') {\n credentialRecordsWithFormatDuplicates.push(record)\n\n // We always extract the first mdoc for querying\n const mdoc = record.firstCredential\n\n return {\n authority: this.getAuthorityForCredential(mdoc),\n credential_format: 'mso_mdoc',\n doctype: mdoc.docType,\n namespaces: mdoc.issuerSignedNamespaces,\n cryptographic_holder_binding: true,\n } satisfies DcqlCredential\n }\n\n if (record.type === 'SdJwtVcRecord') {\n const sdJwtVc = record.firstCredential\n const claims = sdJwtVc.prettyClaims as DcqlSdJwtVcCredential.Claims\n\n // To keep correct mapping of input credential index, we add it multiple times here:\n // - for dc+sd-jwt and vc+sd-jwt\n // - for each extended VCT (until we have multi-vct support in DCQL)\n credentialRecordsWithFormatDuplicates.push(\n record,\n record,\n ...record.extendedVctValues.map(() => record),\n ...record.extendedVctValues.map(() => record)\n )\n\n return [\n {\n authority: this.getAuthorityForCredential(sdJwtVc),\n credential_format: 'dc+sd-jwt',\n vct: record.getTags().vct,\n claims,\n cryptographic_holder_binding: sdJwtVc.holder !== undefined,\n } satisfies DcqlSdJwtVcCredential,\n ...record.extendedVctValues.map(\n (extendedVctValue) =>\n ({\n authority: this.getAuthorityForCredential(sdJwtVc),\n credential_format: 'dc+sd-jwt',\n vct: extendedVctValue,\n claims,\n cryptographic_holder_binding: sdJwtVc.holder !== undefined,\n }) satisfies DcqlSdJwtVcCredential\n ),\n {\n authority: this.getAuthorityForCredential(sdJwtVc),\n credential_format: 'vc+sd-jwt',\n vct: record.getTags().vct,\n claims,\n cryptographic_holder_binding: sdJwtVc.holder !== undefined,\n } satisfies DcqlSdJwtVcCredential,\n ...record.extendedVctValues.map(\n (extendedVctValue) =>\n ({\n authority: this.getAuthorityForCredential(sdJwtVc),\n credential_format: 'vc+sd-jwt',\n vct: extendedVctValue,\n claims,\n cryptographic_holder_binding: sdJwtVc.holder !== undefined,\n }) satisfies DcqlSdJwtVcCredential\n ),\n ] satisfies DcqlSdJwtVcCredential[]\n }\n\n if (record.type === 'W3cCredentialRecord') {\n const firstCredential = record.firstCredential\n credentialRecordsWithFormatDuplicates.push(record)\n if (firstCredential.claimFormat === ClaimFormat.LdpVc) {\n return {\n credential_format: 'ldp_vc',\n authority: this.getAuthorityForCredential(firstCredential),\n type: record.getTags().expandedTypes ?? [],\n claims: firstCredential.jsonCredential as DcqlW3cVcCredential.Claims,\n cryptographic_holder_binding: hasHolderBinding(undefined, firstCredential.credentialSubjectIds),\n } satisfies DcqlW3cVcCredential\n }\n\n return {\n credential_format: 'jwt_vc_json',\n authority: this.getAuthorityForCredential(firstCredential),\n type: firstCredential.type,\n claims: firstCredential.jsonCredential as DcqlW3cVcCredential.Claims,\n cryptographic_holder_binding: hasHolderBinding(undefined, firstCredential.credentialSubjectIds),\n } satisfies DcqlW3cVcCredential\n }\n\n if (record.type === 'W3cV2CredentialRecord') {\n credentialRecordsWithFormatDuplicates.push(record)\n const firstCredential = record.firstCredential\n\n return {\n credential_format: 'vc+sd-jwt',\n authority: this.getAuthorityForCredential(firstCredential),\n type: asArray(firstCredential.resolvedCredential.type),\n claims: firstCredential.resolvedCredential.toJSON() as DcqlW3cVcCredential.Claims,\n cryptographic_holder_binding: hasW3cV2HolderBinding(firstCredential),\n } satisfies DcqlW3cVcCredential\n }\n\n throw new DcqlError('Unsupported record type')\n })\n\n const queryResult = DcqlQuery.query(parsedQuery, dcqlCredentials)\n\n const matchesWithRecord = Object.fromEntries(\n Object.entries(queryResult.credential_matches).map(([credential_query_id, result]) => {\n const failedCredentials = result.failed_credentials\n ? mapNonEmptyArray(result.failed_credentials, (credential) => {\n const record = credentialRecordsWithFormatDuplicates[credential.input_credential_index]\n const updatedCredential: DcqlFailedCredential = {\n ...credential,\n record,\n claims: credential.claims.success\n ? {\n ...credential.claims,\n success: true,\n valid_claim_sets: mapNonEmptyArray(credential.claims.valid_claim_sets, (claimSet) => ({\n ...claimSet,\n ...this.getDisclosedClaimSetOutput(record, claimSet, parsedQuery, credential_query_id),\n })),\n }\n : credential.claims,\n }\n return updatedCredential\n })\n : undefined\n\n // If not success, valid_credentials will be undefined, so we only have to map failed_credentials\n if (!result.success) {\n return [\n credential_query_id,\n {\n ...result,\n failed_credentials: failedCredentials,\n },\n ]\n }\n\n return [\n credential_query_id,\n {\n ...result,\n failed_credentials: failedCredentials,\n valid_credentials: mapNonEmptyArray(result.valid_credentials, (credential) => {\n const record = credentialRecordsWithFormatDuplicates[credential.input_credential_index]\n const updatedCredential: DcqlValidCredential = {\n ...credential,\n record,\n claims: {\n ...credential.claims,\n valid_claim_sets: mapNonEmptyArray(credential.claims.valid_claim_sets, (claimSet) => ({\n ...claimSet,\n ...this.getDisclosedClaimSetOutput(record, claimSet, parsedQuery, credential_query_id),\n })),\n },\n }\n return updatedCredential\n }),\n },\n ]\n })\n )\n\n return {\n ...queryResult,\n credential_matches: matchesWithRecord,\n }\n }\n\n /**\n * What a selectively disclosable credential discloses for the output of a claim set.\n *\n * The output of DCQL only holds the requested claims, while a claim that is not selectively\n * disclosable is always disclosed. So the output is replaced with the claims as the verifier receives\n * them, and `disclosed_paths` added: the paths to those claims in the credential, which are what to\n * disclose when presenting it.\n *\n * Other credentials disclose the output as it is.\n */\n private getDisclosedClaimSetOutput(\n record: DcqlValidCredential['record'],\n claimSet: { output: unknown; valid_claim_indexes?: number[] },\n dcqlQuery: DcqlQuery.Output,\n credentialQueryId: string\n ) {\n // The paths of the claims queries of the claim set, each with the elements a `null` in it selects\n const getClaimPaths = () => {\n const claimsQueries = dcqlQuery.credentials.find((credential) => credential.id === credentialQueryId)?.claims\n const claimsQueryPaths = (claimSet.valid_claim_indexes ?? []).flatMap((index) => {\n const claimsQuery = claimsQueries?.[index]\n // Note path is an array again, we use flatmap, so wrap it in another array, so that if\n // no value is returned ([]) it is not included as undefined in the array\n return claimsQuery && 'path' in claimsQuery ? [claimsQuery.path] : []\n })\n\n return getClaimPathsForDcqlClaimSet(claimsQueryPaths, claimSet.output)\n }\n\n if (record.type === 'SdJwtVcRecord') {\n const { prettyClaims, disclosedPaths } = applyDisclosuresForPaths(record.encoded, getClaimPaths())\n\n return { output: prettyClaims as { [key: string]: JsonValue }, disclosed_paths: disclosedPaths }\n }\n\n if (record.type === 'W3cV2CredentialRecord' && record.firstCredential instanceof W3cV2SdJwtVerifiableCredential) {\n const { prettyClaims, disclosedPaths } = applyDisclosuresForPaths(record.firstCredential.encoded, getClaimPaths())\n\n return {\n // The same shape as the claims DCQL was queried with, which are the credential's JSON\n output: JsonTransformer.fromJSON(prettyClaims, W3cV2Credential, { validate: false }).toJSON() as {\n [key: string]: JsonValue\n },\n disclosed_paths: disclosedPaths,\n }\n }\n\n return {}\n }\n\n public async assertValidDcqlPresentation(\n agentContext: AgentContext,\n dcqlPresentation: DcqlPresentation,\n dcqlQuery: DcqlQuery\n ) {\n const internalDcqlPresentation = Object.fromEntries(\n await Promise.all(\n Object.entries(dcqlPresentation).map(async ([credentialId, presentations]) => {\n const queryCredential = dcqlQuery.credentials.find((c) => c.id === credentialId)\n if (!queryCredential) {\n throw new DcqlError(\n `DCQL presentation contains presentation entry for credential id '${credentialId}', but this id is not present in the DCQL query`\n )\n }\n\n return [\n credentialId,\n await Promise.all(\n presentations.map((presentation) =>\n this.getDcqlCredentialRepresentation(agentContext, presentation, queryCredential)\n )\n ),\n ]\n })\n )\n )\n\n const presentationResult = DcqlPresentationResult.fromDcqlPresentation(internalDcqlPresentation, { dcqlQuery })\n\n if (!presentationResult.can_be_satisfied) {\n throw new DcqlError('Presentations do not satisfy the DCQL query.', {\n additionalMessages: Object.entries(presentationResult.credential_matches ?? {})\n .flatMap(([queryId, match]) =>\n match.success\n ? undefined\n : !match.failed_credentials\n ? `Unable to match query credential '${queryId}'. No prsentations provided`\n : match.failed_credentials.map(\n (failedCredential) =>\n `Presentation at index ${failedCredential.input_credential_index} does not match query credential '${queryId}'. ${JSON.stringify(\n {\n ...(failedCredential.claims.success\n ? {}\n : { claims: failedCredential.claims.failed_claim_sets.map((cs) => cs.issues) }),\n ...(failedCredential.trusted_authorities.success\n ? {}\n : {\n trusted_authorities:\n failedCredential.trusted_authorities.failed_trusted_authorities.map(\n (ta) => ta.issues\n ),\n }),\n ...(failedCredential.meta.success ? {} : { meta: failedCredential.meta.issues }),\n },\n null,\n 2\n )}`\n )\n )\n .filter((message) => message !== undefined),\n })\n }\n\n return presentationResult\n }\n\n private getSelectiveDisclosure(validCredential: DcqlValidCredential): DcqlSelectiveDisclosure {\n const [{ output, disclosed_paths }] = validCredential.claims.valid_claim_sets\n\n return disclosed_paths\n ? { disclosedPaths: disclosed_paths, disclosedPayload: output as JsonObject }\n : { disclosedPayload: output as JsonObject }\n }\n\n private dcqlCredentialForRequestForValidCredential(validCredential: DcqlValidCredential) {\n if (validCredential.record.type === 'MdocRecord') {\n return {\n claimFormat: ClaimFormat.MsoMdoc,\n credentialRecord: validCredential.record,\n disclosedPayload: validCredential.claims.valid_claim_sets[0].output as MdocNameSpaces,\n } as const\n }\n if (validCredential.record.type === 'SdJwtVcRecord') {\n return {\n claimFormat: ClaimFormat.SdJwtDc,\n credentialRecord: validCredential.record,\n ...this.getSelectiveDisclosure(validCredential),\n } as const\n }\n\n if (validCredential.record.type === 'W3cCredentialRecord') {\n return {\n claimFormat: validCredential.record.firstCredential.claimFormat,\n credentialRecord: validCredential.record,\n disclosedPayload: validCredential.record.firstCredential.jsonCredential as JsonObject,\n } as const\n }\n\n if (validCredential.record.type === 'W3cV2CredentialRecord') {\n const claimFormat = validCredential.record.firstCredential.claimFormat\n\n if (claimFormat === ClaimFormat.DiVc) {\n throw new DcqlError('DCQL credential selection does not support W3C V2 Data Integrity credentials yet')\n }\n\n if (claimFormat === ClaimFormat.SdJwtW3cVc) {\n return {\n claimFormat,\n credentialRecord: validCredential.record,\n ...this.getSelectiveDisclosure(validCredential),\n } as const\n }\n\n return {\n claimFormat,\n credentialRecord: validCredential.record,\n disclosedPayload: validCredential.claims.valid_claim_sets[0].output as JsonObject,\n } as const\n }\n\n throw new DcqlError('Unsupported record type for DCQL')\n }\n\n /**\n * Selects the credentials to use based on the output from `getCredentialsForRequest`\n * Use this method if you don't want to manually select the credentials yourself.\n */\n public selectCredentialsForRequest(\n dcqlQueryResult: DcqlQueryResult,\n { useMode = CredentialMultiInstanceUseMode.NewOrFirst }: DcqlSelectCredentialsForRequestOptions = {}\n ): DcqlCredentialsForRequest {\n if (!dcqlQueryResult.can_be_satisfied) {\n throw new DcqlError(\n 'Cannot select the credentials for the dcql query presentation if the request cannot be satisfied'\n )\n }\n\n const credentials: DcqlCredentialsForRequest = {}\n\n if (dcqlQueryResult.credential_sets) {\n credentialSetLoop: for (const credentialSet of dcqlQueryResult.credential_sets) {\n // undefined defaults to true\n if (credentialSet.required === false) continue\n const fullfillableOptions = credentialSet.matching_options\n\n if (!fullfillableOptions) {\n throw new DcqlError('Invalid dcql query result. No option is fullfillable')\n }\n\n for (const fullfillableOption of fullfillableOptions) {\n const optionMatches = fullfillableOption.map((credentialQueryId) => {\n const credentialMatch = dcqlQueryResult.credential_matches[credentialQueryId]\n if (!credentialMatch.success) return undefined\n const match = credentialMatch.valid_credentials.find((match: DcqlValidCredential) =>\n canUseInstanceFromCredentialRecord({ credentialRecord: match.record, useMode })\n )\n\n if (!match) return undefined\n return {\n match,\n credentialQueryId,\n }\n })\n\n if (optionMatches.every((c) => c !== undefined)) {\n for (const { match, credentialQueryId } of optionMatches) {\n credentials[credentialQueryId] = [this.dcqlCredentialForRequestForValidCredential(match)]\n }\n\n continue credentialSetLoop\n }\n }\n\n throw new DcqlError(\n 'Unable to select credentials for credential set. No new credential instance available on any of the available credentials.'\n )\n }\n } else {\n for (const credentialQuery of dcqlQueryResult.credentials) {\n const credentialMatch = dcqlQueryResult.credential_matches[credentialQuery.id]\n if (!credentialMatch.success) {\n throw new DcqlError(\n `Invalid dcql query result for credential query id '${credentialQuery.id}'. Cannot auto-select credentials`\n )\n }\n\n const credential = credentialMatch.valid_credentials.find((match: DcqlValidCredential) =>\n canUseInstanceFromCredentialRecord({ credentialRecord: match.record, useMode })\n )\n if (!credential) {\n throw new DcqlError(\n `Unable to select credential for credential query id '${credentialQuery.id}'. No new credential instance available on any of the available credentials.`\n )\n }\n\n credentials[credentialQuery.id] = [this.dcqlCredentialForRequestForValidCredential(credential)]\n }\n }\n\n return credentials\n }\n\n public validateDcqlQuery(dcqlQuery: DcqlQuery | DcqlQuery.Input | unknown): DcqlQuery {\n const parsed = DcqlQuery.parse(dcqlQuery as DcqlQuery)\n DcqlQuery.validate(parsed)\n return parsed\n }\n\n public async createPresentation(\n agentContext: AgentContext,\n options: {\n credentialQueryToCredential: DcqlCredentialsForRequest\n challenge: string\n domain?: string\n mdocSessionTranscript?: MdocSessionTranscriptOptions\n }\n ): Promise<{\n dcqlPresentation: DcqlPresentation\n encodedDcqlPresentation: DcqlEncodedPresentations\n }> {\n const { domain, challenge, mdocSessionTranscript } = options\n\n const dcqlPresentation: DcqlPresentation = {}\n const encodedDcqlPresentation: DcqlEncodedPresentations = {}\n const vcPresentationsToCreate = getDcqlVcPresentationsToCreate(options.credentialQueryToCredential)\n\n for (const [credentialQueryId, presentationsToCreate] of Object.entries(vcPresentationsToCreate)) {\n for (const presentationToCreate of presentationsToCreate) {\n let createdPresentation: VerifiablePresentation\n let encodedCreatedPresentation: string | Record<string, unknown>\n\n if (presentationToCreate.claimFormat === ClaimFormat.MsoMdoc) {\n const mdocRecord = presentationToCreate.credentialRecord\n if (!mdocSessionTranscript) {\n throw new DcqlError('Missing mdoc session transcript options for creating MDOC presentation.')\n }\n\n const { credentialInstance } = await useInstanceFromCredentialRecord({\n agentContext,\n useMode: presentationToCreate.useMode,\n credentialRecord: mdocRecord,\n })\n\n const deviceResponse = await MdocDeviceResponse.createDeviceResponse(agentContext, {\n mdocs: [credentialInstance],\n documentRequests: [\n {\n docType: mdocRecord.getTags().docType,\n nameSpaces: Object.fromEntries(\n Object.entries(presentationToCreate.disclosedPayload).map(([key, value]) => {\n // FIXME: we need the DCQL query here to get the intent_to_retain from query (currently hardcoded to false)\n return [key, Object.fromEntries(Object.entries(value).map(([key]) => [key, false]))]\n })\n ),\n },\n ],\n sessionTranscriptOptions: mdocSessionTranscript,\n })\n const deviceResponseBase64Url = deviceResponse.encoded\n\n encodedCreatedPresentation = deviceResponseBase64Url\n createdPresentation = MdocDeviceResponse.fromBase64Url(deviceResponseBase64Url)\n } else if (presentationToCreate.claimFormat === ClaimFormat.SdJwtDc) {\n if (!domain) {\n throw new DcqlError('Missing domain property for creating SdJwtVc presentation.')\n }\n\n const { credentialInstance } = await useInstanceFromCredentialRecord({\n agentContext,\n useMode: presentationToCreate.useMode,\n credentialRecord: presentationToCreate.credentialRecord,\n })\n\n const presentationFrame = this.getPresentationFrame(\n typeof credentialInstance === 'string' ? credentialInstance : credentialInstance.compact,\n presentationToCreate\n )\n\n const sdJwtVcApi = this.getSdJwtVcApi(agentContext)\n const presentation = await sdJwtVcApi.present({\n sdJwtVc: credentialInstance,\n presentationFrame,\n verifierMetadata: {\n audience: domain,\n nonce: challenge,\n issuedAt: Math.floor(Date.now() / 1000),\n },\n additionalPayload: presentationToCreate.additionalPayload,\n })\n\n encodedCreatedPresentation = presentation\n createdPresentation = sdJwtVcApi.fromCompact(presentation)\n } else if (presentationToCreate.claimFormat === ClaimFormat.JwtVp) {\n const { credentialInstance } = await useInstanceFromCredentialRecord({\n agentContext,\n useMode: presentationToCreate.useMode,\n credentialRecord: presentationToCreate.credentialRecord,\n })\n\n if (!credentialInstance.credentialSubjectIds[0]) {\n throw new DcqlError('Cannot create presentation for credentials without subject id')\n }\n\n // Determine a suitable verification method for the presentation\n const verificationMethod = await this.getVerificationMethodForSubjectId(\n agentContext,\n credentialInstance.credentialSubjectIds[0]\n )\n\n const w3cCredentialService = agentContext.resolve(W3cCredentialService)\n const w3cPresentation = new W3cPresentation({\n verifiableCredential: [credentialInstance],\n holder: verificationMethod.controller,\n })\n\n const publicJwk = getPublicJwkFromVerificationMethod(verificationMethod)\n\n const signedPresentation = await w3cCredentialService.signPresentation<ClaimFormat.JwtVp>(agentContext, {\n format: ClaimFormat.JwtVp,\n alg: publicJwk.signatureAlgorithm,\n verificationMethod: verificationMethod.id,\n presentation: w3cPresentation,\n challenge,\n domain,\n })\n\n encodedCreatedPresentation = signedPresentation.encoded\n createdPresentation = signedPresentation\n } else if (presentationToCreate.claimFormat === ClaimFormat.LdpVp) {\n const { credentialInstance } = await useInstanceFromCredentialRecord({\n agentContext,\n useMode: presentationToCreate.useMode,\n credentialRecord: presentationToCreate.credentialRecord,\n })\n\n if (!credentialInstance.credentialSubjectIds[0]) {\n throw new DcqlError('Cannot create presentation for credentials without subject id')\n }\n\n // Determine a suitable verification method for the presentation\n const verificationMethod = await this.getVerificationMethodForSubjectId(\n agentContext,\n credentialInstance.credentialSubjectIds[0]\n )\n\n const w3cCredentialService = agentContext.resolve(W3cCredentialService)\n const w3cPresentation = new W3cPresentation({\n verifiableCredential: [credentialInstance],\n holder: verificationMethod.controller,\n })\n\n const signedPresentation = await w3cCredentialService.signPresentation(agentContext, {\n format: ClaimFormat.LdpVp,\n // TODO: we should move the check for which proof to use for a presentation to earlier\n // as then we know when determining which VPs to submit already if the proof types are supported\n // by the verifier, and we can then just add this to the vpToCreate interface\n proofType: this.getProofTypeForLdpVc(agentContext, verificationMethod),\n proofPurpose: new purposes.AuthenticationProofPurpose({ challenge, domain }),\n verificationMethod: verificationMethod.id,\n presentation: w3cPresentation,\n challenge,\n domain,\n })\n\n encodedCreatedPresentation = signedPresentation.encoded\n createdPresentation = signedPresentation\n } else if (presentationToCreate.claimFormat === ClaimFormat.JwtW3cVp) {\n const w3cV2CredentialService = agentContext.resolve(W3cV2CredentialService)\n const firstCredential = presentationToCreate.credentialRecord.firstCredential\n\n if (firstCredential.claimFormat === ClaimFormat.DiVc) {\n throw new DcqlError('DCQL JWT W3C VP creation does not support W3C V2 Data Integrity credentials yet')\n }\n\n const w3cV2Presentation = new W3cV2Presentation({\n holder: firstCredential.resolvedCredential.credentialSubjectIds[0],\n verifiableCredential: [W3cV2EnvelopedVerifiableCredential.fromVerifiableCredential(firstCredential)],\n })\n\n const signedPresentation = await w3cV2CredentialService.signPresentation<ClaimFormat.JwtW3cVp>(agentContext, {\n format: ClaimFormat.JwtW3cVp,\n presentation: w3cV2Presentation,\n challenge,\n domain,\n })\n\n encodedCreatedPresentation = signedPresentation.encoded\n createdPresentation = signedPresentation\n } else if (presentationToCreate.claimFormat === ClaimFormat.SdJwtW3cVp) {\n const presentationFrame = this.getPresentationFrame(\n presentationToCreate.credentialRecord.firstCredential.encoded,\n presentationToCreate\n )\n if (!domain) {\n throw new DcqlError('Missing domain property for creating SdJwtVc presentation.')\n }\n\n const w3cV2SdJwtCredentialService = agentContext.resolve(W3cV2SdJwtCredentialService)\n const sdJwtVc = await w3cV2SdJwtCredentialService.present(agentContext, {\n credential: presentationToCreate.credentialRecord.firstCredential.encoded,\n presentationFrame,\n })\n\n const w3cV2CredentialService = agentContext.resolve(W3cV2CredentialService)\n const w3cV2Presentation = new W3cV2Presentation({\n holder: presentationToCreate.credentialRecord.firstCredential.resolvedCredential.credentialSubjectIds[0],\n verifiableCredential: [W3cV2EnvelopedVerifiableCredential.fromVerifiableCredential(sdJwtVc)],\n })\n\n const signedPresentation = await w3cV2CredentialService.signPresentation<ClaimFormat.SdJwtW3cVp>(\n agentContext,\n {\n format: ClaimFormat.SdJwtW3cVp,\n presentation: w3cV2Presentation,\n challenge,\n domain,\n }\n )\n\n encodedCreatedPresentation = signedPresentation.encoded\n createdPresentation = signedPresentation\n } else {\n throw new DcqlError('Unsupported presentation format.')\n }\n\n if (!dcqlPresentation[credentialQueryId]) {\n dcqlPresentation[credentialQueryId] = [createdPresentation]\n } else {\n dcqlPresentation[credentialQueryId].push(createdPresentation)\n }\n\n if (!encodedDcqlPresentation[credentialQueryId]) {\n encodedDcqlPresentation[credentialQueryId] = [encodedCreatedPresentation]\n } else {\n encodedDcqlPresentation[credentialQueryId].push(encodedCreatedPresentation)\n }\n }\n }\n\n return {\n dcqlPresentation,\n encodedDcqlPresentation,\n }\n }\n\n private getPresentationFrame(\n compactSdJwt: string,\n { disclosedPaths, disclosedPayload }: { disclosedPaths?: ClaimPath[]; disclosedPayload?: JsonObject }\n ) {\n if (disclosedPaths) return buildPresentationFrameForPaths(compactSdJwt, disclosedPaths)\n // DisclosedPayload will be removed in future version\n if (disclosedPayload) return buildDisclosureFrameForPayload(disclosedPayload)\n\n throw new DcqlError(\n 'Either disclosedPaths or disclosedPayload is required to present a selectively disclosable credential.'\n )\n }\n\n private getSdJwtVcApi(agentContext: AgentContext) {\n return agentContext.dependencyManager.resolve(SdJwtVcApi)\n }\n\n private getMdocApi(agentContext: AgentContext) {\n return agentContext.dependencyManager.resolve(MdocApi)\n }\n\n private async getVerificationMethodForSubjectId(agentContext: AgentContext, subjectId: string) {\n const didsApi = agentContext.dependencyManager.resolve(DidsApi)\n\n if (!subjectId.startsWith('did:')) {\n throw new DcqlError(`Only dids are supported as credentialSubject id. ${subjectId} is not a valid did`)\n }\n\n const didDocument = await didsApi.resolveDidDocument(subjectId)\n\n if (!didDocument.authentication || didDocument.authentication.length === 0) {\n throw new DcqlError(`No authentication verificationMethods found for did ${subjectId} in did document`)\n }\n\n // the signature suite to use for the presentation is dependant on the credentials we share.\n // 1. Get the verification method for this given proof purpose in this DID document\n const [verificationMethod] = didDocument.findVerificationMethodsByPurpose(['authentication'])\n return verificationMethod\n }\n\n // FIXME: We need to take into account OpenID4VP metadata (probably providing supported/allowed algs to the DCQL create presentation method)\n private getProofTypeForLdpVc(agentContext: AgentContext, verificationMethod: VerificationMethod) {\n // For each of the supported algs, find the key types, then find the proof types\n const signatureSuiteRegistry = agentContext.dependencyManager.resolve(SignatureSuiteRegistry)\n\n const publicJwk = getPublicJwkFromVerificationMethod(verificationMethod)\n const supportedSignatureSuites = signatureSuiteRegistry.getAllByPublicJwkType(publicJwk)\n if (supportedSignatureSuites.length === 0) {\n throw new DcqlError(\n `Couldn't find a supported signature suite for the given jwk ${publicJwk.jwkTypeHumanDescription}`\n )\n }\n\n return supportedSignatureSuites[0].proofType\n }\n}\n\n/**\n * A credential is bound to its holder through a key (`cnf`) or its subject. Verifying a presentation\n * checks that the presenter proves the binding. A subject id that is not a DID also counts, so such\n * a credential can't be presented.\n */\nfunction hasHolderBinding(cnf: unknown, credentialSubjectIds: string[]) {\n return cnf !== undefined || credentialSubjectIds.length > 0\n}\n\nfunction hasW3cV2HolderBinding(credential: W3cV2VerifiableCredential) {\n const cnf =\n credential instanceof W3cV2SdJwtVerifiableCredential\n ? credential.sdJwt.prettyClaims.cnf\n : credential instanceof W3cV2JwtVerifiableCredential\n ? credential.jwt.payload.additionalClaims.cnf\n : undefined\n\n return hasHolderBinding(cnf, credential.resolvedCredential.credentialSubjectIds)\n}\n"],"mappings":"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"}
@@ -20,6 +20,10 @@ export declare class DidResolverService {
20
20
  */
21
21
  resolveDidDocument(agentContext: AgentContext, did: string): Promise<DidDocument>;
22
22
  invalidateCacheForDid(agentContext: AgentContext, did: string): Promise<void>;
23
+ /**
24
+ * A short form did:peer:4 resolves to the document of its long form, which is bound to it by hash.
25
+ */
26
+ private ensureDidDocumentIdMatchesDid;
23
27
  private getCacheKeyAndScope;
24
28
  private findResolver;
25
29
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"DidResolverService.d.mts","names":[],"sources":["../../../../src/modules/dids/services/DidResolverService.ts"],"mappings":";;;;;;;;;;qBAea;UACH;UACA;UACA;EAG2B,YAAA,QAAQ,QACzC,kBAAkB,kBAClB,eAAe;EAOJ,QACX,cAAc,cACd,gBACA,UAAS,uBACR,QAAQ;;;;;EAiHE,mBAAmB,cAAc,cAAc,cAAW,QAAA;EAY1D,sBAAsB,cAAc,cAAc,cAAW;UAelE;UAOA;;;;MAOG"}
1
+ {"version":3,"file":"DidResolverService.d.mts","names":[],"sources":["../../../../src/modules/dids/services/DidResolverService.ts"],"mappings":";;;;;;;;;;qBAgBa;UACH;UACA;UACA;EAG2B,YAAA,QAAQ,QACzC,kBAAkB,kBAClB,eAAe;EAOJ,QACX,cAAc,cACd,gBACA,UAAS,uBACR,QAAQ;;;;;EAoHE,mBAAmB,cAAc,cAAc,cAAW,QAAA;EAY1D,sBAAsB,cAAc,cAAc,cAAW;;;;UAkBlE;UAcA;UAOA;;;;MAOG"}
@@ -14,6 +14,7 @@ import { DidDocument } from "../domain/DidDocument.mjs";
14
14
  import "../domain/index.mjs";
15
15
  import { DidRepository } from "../repository/DidRepository.mjs";
16
16
  import "../repository/index.mjs";
17
+ import { getAlternativeDidsForNumAlgo4Did } from "../methods/peer/peerDidNumAlgo4.mjs";
17
18
  import { DidsModuleConfig } from "../DidsModuleConfig.mjs";
18
19
  //#region src/modules/dids/services/DidResolverService.ts
19
20
  let DidResolverService = class DidResolverService {
@@ -50,27 +51,27 @@ let DidResolverService = class DidResolverService {
50
51
  const { cacheKey, cacheScope } = this.getCacheKeyAndScope(parsed);
51
52
  if (resolver.allowsCaching && useCache) {
52
53
  const cachedDidDocument = await agentContext.dependencyManager.resolve(CacheModuleConfig).cache.get(agentContext, cacheKey, { scope: cacheScope });
53
- if (cachedDidDocument) return {
54
+ if (cachedDidDocument) return this.ensureDidDocumentIdMatchesDid(parsed, {
54
55
  ...cachedDidDocument,
55
56
  didDocument: JsonTransformer.fromJSON(cachedDidDocument.didDocument, DidDocument),
56
57
  didResolutionMetadata: {
57
58
  ...cachedDidDocument.didResolutionMetadata,
58
59
  servedFromCache: true
59
60
  }
60
- };
61
+ });
61
62
  }
62
63
  if (resolver.allowsLocalDidRecord && useLocalCreatedDidRecord) {
63
64
  const [didRecord] = await this.didRepository.getCreatedDids(agentContext, { did: parsed.did });
64
- if (didRecord?.didDocument) return {
65
+ if (didRecord?.didDocument) return this.ensureDidDocumentIdMatchesDid(parsed, {
65
66
  didDocument: didRecord.didDocument,
66
67
  didDocumentMetadata: {},
67
68
  didResolutionMetadata: {
68
69
  servedFromCache: false,
69
70
  servedFromDidRecord: true
70
71
  }
71
- };
72
+ });
72
73
  }
73
- let resolutionResult = await resolver.resolve(agentContext, parsed.did, parsed, options);
74
+ let resolutionResult = this.ensureDidDocumentIdMatchesDid(parsed, await resolver.resolve(agentContext, parsed.did, parsed, options));
74
75
  resolutionResult = {
75
76
  ...resolutionResult,
76
77
  didResolutionMetadata: {
@@ -105,6 +106,21 @@ let DidResolverService = class DidResolverService {
105
106
  const { cacheKey, cacheScope } = this.getCacheKeyAndScope(parsed);
106
107
  await cache.remove(agentContext, cacheKey, { scope: cacheScope });
107
108
  }
109
+ /**
110
+ * A short form did:peer:4 resolves to the document of its long form, which is bound to it by hash.
111
+ */
112
+ ensureDidDocumentIdMatchesDid(parsed, result) {
113
+ const id = result.didDocument?.id;
114
+ if (!id || id === parsed.did || getAlternativeDidsForNumAlgo4Did(id)?.includes(parsed.did)) return result;
115
+ return {
116
+ didDocument: null,
117
+ didDocumentMetadata: {},
118
+ didResolutionMetadata: {
119
+ error: "invalidDidDocument",
120
+ message: `DID document id '${id}' does not match the resolved did '${parsed.did}'`
121
+ }
122
+ };
123
+ }
108
124
  getCacheKeyAndScope(parsed) {
109
125
  return {
110
126
  cacheKey: `did:resolver:${parsed.did}`,
@@ -1 +1 @@
1
- {"version":3,"file":"DidResolverService.mjs","names":[],"sources":["../../../../src/modules/dids/services/DidResolverService.ts"],"sourcesContent":["import type { AgentContext } from '../../../agent'\nimport { InjectionSymbols } from '../../../constants'\nimport { CredoError } from '../../../error'\nimport type { Logger } from '../../../logger'\nimport { inject, injectable } from '../../../plugins'\nimport { JsonTransformer } from '../../../utils'\nimport { CacheModuleConfig } from '../../cache'\nimport { DidsModuleConfig } from '../DidsModuleConfig'\nimport { DidDocument } from '../domain'\nimport type { DidResolver } from '../domain/DidResolver'\nimport { parseDid } from '../domain/parse'\nimport { DidRepository } from '../repository'\nimport type { DidResolutionOptions, DidResolutionResult, ParsedDid } from '../types'\n\n@injectable()\nexport class DidResolverService {\n private logger: Logger\n private didsModuleConfig: DidsModuleConfig\n private didRepository: DidRepository\n\n public constructor(\n @inject(InjectionSymbols.Logger) logger: Logger,\n didsModuleConfig: DidsModuleConfig,\n didRepository: DidRepository\n ) {\n this.logger = logger\n this.didsModuleConfig = didsModuleConfig\n this.didRepository = didRepository\n }\n\n public async resolve(\n agentContext: AgentContext,\n didUrl: string,\n options: DidResolutionOptions = {}\n ): Promise<DidResolutionResult> {\n this.logger.debug(`resolving didUrl ${didUrl}`)\n\n const result = {\n didResolutionMetadata: {},\n didDocument: null,\n didDocumentMetadata: {},\n }\n\n let parsed: ParsedDid\n try {\n parsed = parseDid(didUrl)\n } catch (_error) {\n return {\n ...result,\n didResolutionMetadata: { error: 'invalidDid' },\n }\n }\n\n const resolver = this.findResolver(parsed)\n if (!resolver) {\n return {\n ...result,\n didResolutionMetadata: {\n error: 'unsupportedDidMethod',\n message: `No did resolver registered for did method ${parsed.method}`,\n },\n }\n }\n\n // extract caching options and set defaults\n const {\n useCache = true,\n cacheDurationInSeconds = 300,\n persistInCache = true,\n useLocalCreatedDidRecord = true,\n } = options\n const { cacheKey, cacheScope } = this.getCacheKeyAndScope(parsed)\n\n if (resolver.allowsCaching && useCache) {\n const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache\n const cachedDidDocument = await cache.get<DidResolutionResult & { didDocument: Record<string, unknown> }>(\n agentContext,\n cacheKey,\n { scope: cacheScope }\n )\n\n if (cachedDidDocument) {\n return {\n ...cachedDidDocument,\n didDocument: JsonTransformer.fromJSON(cachedDidDocument.didDocument, DidDocument),\n didResolutionMetadata: {\n ...cachedDidDocument.didResolutionMetadata,\n servedFromCache: true,\n },\n }\n }\n }\n\n // TODO: we should store the document for future reference\n if (resolver.allowsLocalDidRecord && useLocalCreatedDidRecord) {\n // TODO: did should have tag whether a did document is present in the did record\n const [didRecord] = await this.didRepository.getCreatedDids(agentContext, {\n did: parsed.did,\n })\n\n if (didRecord?.didDocument) {\n return {\n didDocument: didRecord.didDocument,\n didDocumentMetadata: {},\n didResolutionMetadata: {\n servedFromCache: false,\n servedFromDidRecord: true,\n },\n }\n }\n }\n\n let resolutionResult = await resolver.resolve(agentContext, parsed.did, parsed, options)\n // Avoid overwriting existing document\n resolutionResult = {\n ...resolutionResult,\n didResolutionMetadata: {\n ...resolutionResult.didResolutionMetadata,\n resolutionTime: Date.now(),\n // Did resolver implementation might use did method specific caching strategy\n // We only set to false if not defined by the resolver\n servedFromCache: resolutionResult.didResolutionMetadata.servedFromCache ?? false,\n },\n }\n\n if (resolutionResult.didDocument && resolver.allowsCaching && persistInCache) {\n const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache\n await cache.set(\n agentContext,\n cacheKey,\n {\n ...resolutionResult,\n didDocument: resolutionResult.didDocument.toJSON(),\n },\n // Set cache duration\n cacheDurationInSeconds,\n { scope: cacheScope }\n )\n }\n\n return resolutionResult\n }\n\n /**\n * Resolve a did document. This uses the default resolution options, and thus\n * will use caching if available.\n */\n public async resolveDidDocument(agentContext: AgentContext, did: string) {\n const {\n didDocument,\n didResolutionMetadata: { error, message },\n } = await this.resolve(agentContext, did)\n\n if (!didDocument) {\n throw new CredoError(`Unable to resolve did document for did '${did}': ${error} ${message}`)\n }\n return didDocument\n }\n\n public async invalidateCacheForDid(agentContext: AgentContext, did: string) {\n const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache\n\n let parsed: ParsedDid\n try {\n parsed = parseDid(did)\n } catch (_error) {\n // If the did is invalid, there is no cache to invalidate, so we can just return\n return\n }\n\n const { cacheKey, cacheScope } = this.getCacheKeyAndScope(parsed)\n await cache.remove(agentContext, cacheKey, { scope: cacheScope })\n }\n\n private getCacheKeyAndScope(parsed: ParsedDid): { cacheKey: string; cacheScope: 'context' | 'global' } {\n return {\n cacheKey: `did:resolver:${parsed.did}`,\n cacheScope: this.didsModuleConfig.publicDidMethods.includes(parsed.method) ? 'global' : 'context',\n }\n }\n\n private findResolver(parsed: ParsedDid): DidResolver | null {\n return this.didsModuleConfig.resolvers.find((r) => r.supportedMethods.includes(parsed.method)) ?? null\n }\n\n /**\n * Get all supported did methods for the did resolver.\n */\n public get supportedMethods() {\n return Array.from(new Set(this.didsModuleConfig.resolvers.flatMap((r) => r.supportedMethods)))\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAeO,IAAM,qBAAN,MAAM,mBAAmB;CAK9B,YACE,QACA,kBACA,eACA;EACA,KAAK,SAAS;EACd,KAAK,mBAAmB;EACxB,KAAK,gBAAgB;CACvB;CAEA,MAAa,QACX,cACA,QACA,UAAgC,CAAC,GACH;EAC9B,KAAK,OAAO,MAAM,oBAAoB,QAAQ;EAE9C,MAAM,SAAS;GACb,uBAAuB,CAAC;GACxB,aAAa;GACb,qBAAqB,CAAC;EACxB;EAEA,IAAI;EACJ,IAAI;GACF,SAAS,SAAS,MAAM;EAC1B,SAAS,QAAQ;GACf,OAAO;IACL,GAAG;IACH,uBAAuB,EAAE,OAAO,aAAa;GAC/C;EACF;EAEA,MAAM,WAAW,KAAK,aAAa,MAAM;EACzC,IAAI,CAAC,UACH,OAAO;GACL,GAAG;GACH,uBAAuB;IACrB,OAAO;IACP,SAAS,6CAA6C,OAAO;GAC/D;EACF;EAIF,MAAM,EACJ,WAAW,MACX,yBAAyB,KACzB,iBAAiB,MACjB,2BAA2B,SACzB;EACJ,MAAM,EAAE,UAAU,eAAe,KAAK,oBAAoB,MAAM;EAEhE,IAAI,SAAS,iBAAiB,UAAU;GAEtC,MAAM,oBAAoB,MADZ,aAAa,kBAAkB,QAAQ,iBAAiB,CAAC,CAAC,MAClC,IACpC,cACA,UACA,EAAE,OAAO,WAAW,CACtB;GAEA,IAAI,mBACF,OAAO;IACL,GAAG;IACH,aAAa,gBAAgB,SAAS,kBAAkB,aAAa,WAAW;IAChF,uBAAuB;KACrB,GAAG,kBAAkB;KACrB,iBAAiB;IACnB;GACF;EAEJ;EAGA,IAAI,SAAS,wBAAwB,0BAA0B;GAE7D,MAAM,CAAC,aAAa,MAAM,KAAK,cAAc,eAAe,cAAc,EACxE,KAAK,OAAO,IACd,CAAC;GAED,IAAI,WAAW,aACb,OAAO;IACL,aAAa,UAAU;IACvB,qBAAqB,CAAC;IACtB,uBAAuB;KACrB,iBAAiB;KACjB,qBAAqB;IACvB;GACF;EAEJ;EAEA,IAAI,mBAAmB,MAAM,SAAS,QAAQ,cAAc,OAAO,KAAK,QAAQ,OAAO;EAEvF,mBAAmB;GACjB,GAAG;GACH,uBAAuB;IACrB,GAAG,iBAAiB;IACpB,gBAAgB,KAAK,IAAI;IAGzB,iBAAiB,iBAAiB,sBAAsB,mBAAmB;GAC7E;EACF;EAEA,IAAI,iBAAiB,eAAe,SAAS,iBAAiB,gBAE5D,MADc,aAAa,kBAAkB,QAAQ,iBAAiB,CAAC,CAAC,MAC5D,IACV,cACA,UACA;GACE,GAAG;GACH,aAAa,iBAAiB,YAAY,OAAO;EACnD,GAEA,wBACA,EAAE,OAAO,WAAW,CACtB;EAGF,OAAO;CACT;;;;;CAMA,MAAa,mBAAmB,cAA4B,KAAa;EACvE,MAAM,EACJ,aACA,uBAAuB,EAAE,OAAO,cAC9B,MAAM,KAAK,QAAQ,cAAc,GAAG;EAExC,IAAI,CAAC,aACH,MAAM,IAAI,WAAW,2CAA2C,IAAI,KAAK,MAAM,GAAG,SAAS;EAE7F,OAAO;CACT;CAEA,MAAa,sBAAsB,cAA4B,KAAa;EAC1E,MAAM,QAAQ,aAAa,kBAAkB,QAAQ,iBAAiB,CAAC,CAAC;EAExE,IAAI;EACJ,IAAI;GACF,SAAS,SAAS,GAAG;EACvB,SAAS,QAAQ;GAEf;EACF;EAEA,MAAM,EAAE,UAAU,eAAe,KAAK,oBAAoB,MAAM;EAChE,MAAM,MAAM,OAAO,cAAc,UAAU,EAAE,OAAO,WAAW,CAAC;CAClE;CAEA,oBAA4B,QAA2E;EACrG,OAAO;GACL,UAAU,gBAAgB,OAAO;GACjC,YAAY,KAAK,iBAAiB,iBAAiB,SAAS,OAAO,MAAM,IAAI,WAAW;EAC1F;CACF;CAEA,aAAqB,QAAuC;EAC1D,OAAO,KAAK,iBAAiB,UAAU,MAAM,MAAM,EAAE,iBAAiB,SAAS,OAAO,MAAM,CAAC,KAAK;CACpG;;;;CAKA,IAAW,mBAAmB;EAC5B,OAAO,MAAM,KAAK,IAAI,IAAI,KAAK,iBAAiB,UAAU,SAAS,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC/F;AACF;;CAjLC,WAAW;CAOP,gBAAA,GAAA,OAAO,iBAAiB,MAAM,CAAA"}
1
+ {"version":3,"file":"DidResolverService.mjs","names":[],"sources":["../../../../src/modules/dids/services/DidResolverService.ts"],"sourcesContent":["import type { AgentContext } from '../../../agent'\nimport { InjectionSymbols } from '../../../constants'\nimport { CredoError } from '../../../error'\nimport type { Logger } from '../../../logger'\nimport { inject, injectable } from '../../../plugins'\nimport { JsonTransformer } from '../../../utils'\nimport { CacheModuleConfig } from '../../cache'\nimport { DidsModuleConfig } from '../DidsModuleConfig'\nimport { DidDocument } from '../domain'\nimport type { DidResolver } from '../domain/DidResolver'\nimport { parseDid } from '../domain/parse'\nimport { getAlternativeDidsForNumAlgo4Did } from '../methods/peer/peerDidNumAlgo4'\nimport { DidRepository } from '../repository'\nimport type { DidResolutionOptions, DidResolutionResult, ParsedDid } from '../types'\n\n@injectable()\nexport class DidResolverService {\n private logger: Logger\n private didsModuleConfig: DidsModuleConfig\n private didRepository: DidRepository\n\n public constructor(\n @inject(InjectionSymbols.Logger) logger: Logger,\n didsModuleConfig: DidsModuleConfig,\n didRepository: DidRepository\n ) {\n this.logger = logger\n this.didsModuleConfig = didsModuleConfig\n this.didRepository = didRepository\n }\n\n public async resolve(\n agentContext: AgentContext,\n didUrl: string,\n options: DidResolutionOptions = {}\n ): Promise<DidResolutionResult> {\n this.logger.debug(`resolving didUrl ${didUrl}`)\n\n const result = {\n didResolutionMetadata: {},\n didDocument: null,\n didDocumentMetadata: {},\n }\n\n let parsed: ParsedDid\n try {\n parsed = parseDid(didUrl)\n } catch (_error) {\n return {\n ...result,\n didResolutionMetadata: { error: 'invalidDid' },\n }\n }\n\n const resolver = this.findResolver(parsed)\n if (!resolver) {\n return {\n ...result,\n didResolutionMetadata: {\n error: 'unsupportedDidMethod',\n message: `No did resolver registered for did method ${parsed.method}`,\n },\n }\n }\n\n // extract caching options and set defaults\n const {\n useCache = true,\n cacheDurationInSeconds = 300,\n persistInCache = true,\n useLocalCreatedDidRecord = true,\n } = options\n const { cacheKey, cacheScope } = this.getCacheKeyAndScope(parsed)\n\n if (resolver.allowsCaching && useCache) {\n const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache\n const cachedDidDocument = await cache.get<DidResolutionResult & { didDocument: Record<string, unknown> }>(\n agentContext,\n cacheKey,\n { scope: cacheScope }\n )\n\n if (cachedDidDocument) {\n return this.ensureDidDocumentIdMatchesDid(parsed, {\n ...cachedDidDocument,\n didDocument: JsonTransformer.fromJSON(cachedDidDocument.didDocument, DidDocument),\n didResolutionMetadata: {\n ...cachedDidDocument.didResolutionMetadata,\n servedFromCache: true,\n },\n })\n }\n }\n\n // TODO: we should store the document for future reference\n if (resolver.allowsLocalDidRecord && useLocalCreatedDidRecord) {\n // TODO: did should have tag whether a did document is present in the did record\n const [didRecord] = await this.didRepository.getCreatedDids(agentContext, {\n did: parsed.did,\n })\n\n if (didRecord?.didDocument) {\n return this.ensureDidDocumentIdMatchesDid(parsed, {\n didDocument: didRecord.didDocument,\n didDocumentMetadata: {},\n didResolutionMetadata: {\n servedFromCache: false,\n servedFromDidRecord: true,\n },\n })\n }\n }\n\n let resolutionResult = this.ensureDidDocumentIdMatchesDid(\n parsed,\n await resolver.resolve(agentContext, parsed.did, parsed, options)\n )\n // Avoid overwriting existing document\n resolutionResult = {\n ...resolutionResult,\n didResolutionMetadata: {\n ...resolutionResult.didResolutionMetadata,\n resolutionTime: Date.now(),\n // Did resolver implementation might use did method specific caching strategy\n // We only set to false if not defined by the resolver\n servedFromCache: resolutionResult.didResolutionMetadata.servedFromCache ?? false,\n },\n }\n\n if (resolutionResult.didDocument && resolver.allowsCaching && persistInCache) {\n const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache\n await cache.set(\n agentContext,\n cacheKey,\n {\n ...resolutionResult,\n didDocument: resolutionResult.didDocument.toJSON(),\n },\n // Set cache duration\n cacheDurationInSeconds,\n { scope: cacheScope }\n )\n }\n\n return resolutionResult\n }\n\n /**\n * Resolve a did document. This uses the default resolution options, and thus\n * will use caching if available.\n */\n public async resolveDidDocument(agentContext: AgentContext, did: string) {\n const {\n didDocument,\n didResolutionMetadata: { error, message },\n } = await this.resolve(agentContext, did)\n\n if (!didDocument) {\n throw new CredoError(`Unable to resolve did document for did '${did}': ${error} ${message}`)\n }\n return didDocument\n }\n\n public async invalidateCacheForDid(agentContext: AgentContext, did: string) {\n const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache\n\n let parsed: ParsedDid\n try {\n parsed = parseDid(did)\n } catch (_error) {\n // If the did is invalid, there is no cache to invalidate, so we can just return\n return\n }\n\n const { cacheKey, cacheScope } = this.getCacheKeyAndScope(parsed)\n await cache.remove(agentContext, cacheKey, { scope: cacheScope })\n }\n\n /**\n * A short form did:peer:4 resolves to the document of its long form, which is bound to it by hash.\n */\n private ensureDidDocumentIdMatchesDid(parsed: ParsedDid, result: DidResolutionResult): DidResolutionResult {\n const id = result.didDocument?.id\n if (!id || id === parsed.did || getAlternativeDidsForNumAlgo4Did(id)?.includes(parsed.did)) return result\n\n return {\n didDocument: null,\n didDocumentMetadata: {},\n didResolutionMetadata: {\n error: 'invalidDidDocument',\n message: `DID document id '${id}' does not match the resolved did '${parsed.did}'`,\n },\n }\n }\n\n private getCacheKeyAndScope(parsed: ParsedDid): { cacheKey: string; cacheScope: 'context' | 'global' } {\n return {\n cacheKey: `did:resolver:${parsed.did}`,\n cacheScope: this.didsModuleConfig.publicDidMethods.includes(parsed.method) ? 'global' : 'context',\n }\n }\n\n private findResolver(parsed: ParsedDid): DidResolver | null {\n return this.didsModuleConfig.resolvers.find((r) => r.supportedMethods.includes(parsed.method)) ?? null\n }\n\n /**\n * Get all supported did methods for the did resolver.\n */\n public get supportedMethods() {\n return Array.from(new Set(this.didsModuleConfig.resolvers.flatMap((r) => r.supportedMethods)))\n }\n}\n"],"mappings":"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"}
@@ -19,20 +19,20 @@ async function resolveSigningPublicJwkFromDidUrl(agentContext, didUrl) {
19
19
  const { publicJwk } = await agentContext.dependencyManager.resolve(DidsApi).resolveVerificationMethodFromCreatedDidRecord(didUrl);
20
20
  return publicJwk;
21
21
  }
22
- async function resolveDidUrl(agentContext, didUrl) {
22
+ async function resolveDidUrl(agentContext, didUrl, purposes = ["assertionMethod"]) {
23
23
  const didDocument = await agentContext.dependencyManager.resolve(DidResolverService).resolveDidDocument(agentContext, didUrl);
24
24
  return {
25
- verificationMethod: didDocument.dereferenceKey(didUrl, ["assertionMethod"]),
25
+ verificationMethod: didDocument.dereferenceKey(didUrl, purposes),
26
26
  didDocument
27
27
  };
28
28
  }
29
- async function extractKeyFromHolderBinding(agentContext, holder, { forSigning = false, jwkKeyId } = {}) {
29
+ async function extractKeyFromHolderBinding(agentContext, holder, { forSigning = false, jwkKeyId, didPurposes } = {}) {
30
30
  if (holder.method === "did") {
31
31
  if (!parseDid(holder.didUrl).fragment) throw new CredoError(`didUrl '${holder.didUrl}' does not contain a '#'. Unable to derive key from did document`);
32
32
  let publicJwk;
33
33
  if (forSigning) publicJwk = await resolveSigningPublicJwkFromDidUrl(agentContext, holder.didUrl);
34
34
  else {
35
- const { verificationMethod } = await resolveDidUrl(agentContext, holder.didUrl);
35
+ const { verificationMethod } = await resolveDidUrl(agentContext, holder.didUrl, didPurposes);
36
36
  publicJwk = getPublicJwkFromVerificationMethod(verificationMethod);
37
37
  }
38
38
  const supportedSignatureAlgorithms = publicJwk.supportedSignatureAlgorithms;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","names":[],"sources":["../../../src/modules/sd-jwt-vc/utils.ts"],"sourcesContent":["import type { Signer, Verifier } from '@sd-jwt/core'\nimport { AgentContext } from '../../agent'\nimport type { HashName } from '../../crypto'\nimport { CredoError } from '../../error'\nimport { TypedArrayEncoder } from '../../utils'\nimport { DidResolverService, DidsApi, getPublicJwkFromVerificationMethod, parseDid } from '../dids'\nimport { isKnownJwaSignatureAlgorithm, type Jwk, KeyManagementApi, PublicJwk } from '../kms'\nimport { X509Certificate } from '../x509/X509Certificate'\nimport { SdJwtVcError } from './SdJwtVcError'\nimport type { SdJwtVcHolderBinding, SdJwtVcIssuer } from './SdJwtVcOptions'\n\nexport async function resolveSigningPublicJwkFromDidUrl(agentContext: AgentContext, didUrl: string) {\n const dids = agentContext.dependencyManager.resolve(DidsApi)\n\n const { publicJwk } = await dids.resolveVerificationMethodFromCreatedDidRecord(didUrl)\n return publicJwk\n}\n\nexport async function resolveDidUrl(agentContext: AgentContext, didUrl: string) {\n const didResolver = agentContext.dependencyManager.resolve(DidResolverService)\n const didDocument = await didResolver.resolveDidDocument(agentContext, didUrl)\n\n return {\n verificationMethod: didDocument.dereferenceKey(didUrl, ['assertionMethod']),\n didDocument,\n }\n}\n\nexport async function extractKeyFromHolderBinding(\n agentContext: AgentContext,\n holder: SdJwtVcHolderBinding,\n { forSigning = false, jwkKeyId }: { forSigning?: boolean; jwkKeyId?: string } = {}\n) {\n if (holder.method === 'did') {\n const parsedDid = parseDid(holder.didUrl)\n if (!parsedDid.fragment) {\n throw new CredoError(`didUrl '${holder.didUrl}' does not contain a '#'. Unable to derive key from did document`)\n }\n\n let publicJwk: PublicJwk\n if (forSigning) {\n publicJwk = await resolveSigningPublicJwkFromDidUrl(agentContext, holder.didUrl)\n } else {\n const { verificationMethod } = await resolveDidUrl(agentContext, holder.didUrl)\n publicJwk = getPublicJwkFromVerificationMethod(verificationMethod)\n }\n\n const supportedSignatureAlgorithms = publicJwk.supportedSignatureAlgorithms\n if (supportedSignatureAlgorithms.length === 0) {\n throw new CredoError(`No supported JWA signature algorithms found for key ${publicJwk.jwkTypeHumanDescription}`)\n }\n const alg = supportedSignatureAlgorithms[0]\n\n return {\n alg,\n publicJwk,\n cnf: {\n // We need to include the whole didUrl here, otherwise the verifier\n // won't know which did it is associated with\n kid: holder.didUrl,\n },\n }\n }\n if (holder.method === 'jwk') {\n const publicJwk = holder.jwk\n const alg = publicJwk.supportedSignatureAlgorithms[0]\n\n if (forSigning) {\n publicJwk.keyId = jwkKeyId ?? publicJwk.legacyKeyId\n }\n\n return {\n alg,\n publicJwk,\n cnf: {\n jwk: publicJwk.toJson(),\n },\n }\n }\n\n throw new CredoError(\"Unsupported credential holder binding. Only 'did' and 'jwk' are supported at the moment.\")\n}\n\n/**\n * Set the `alg` from a JWT header on the public jwk, so signing and verification use the\n * algorithm of the JWT rather than the first supported signature algorithm of the key.\n *\n * Throws an error if the alg is not a known JWA signature algorithm, or if the alg is not\n * supported by the jwk.\n */\nexport function setJwkAlgFromJwtHeader(publicJwk: PublicJwk, jwtHeaderAlg: unknown) {\n if (typeof jwtHeaderAlg !== 'string' || !isKnownJwaSignatureAlgorithm(jwtHeaderAlg)) {\n throw new CredoError(`Expected JWT header 'alg' to be a known JWA signature algorithm, found '${jwtHeaderAlg}'`)\n }\n\n publicJwk.alg = jwtHeaderAlg\n}\n\n/**\n * Hashing algorithms that can be used for the disclosure digests of an SD-JWT, and are placed\n * in the `_sd_alg` claim.\n *\n * `sha-1` is omitted, as SD-JWT requires a hash algorithm that is considered secure at the\n * time of issuance.\n *\n * @see https://www.ietf.org/archive/id/draft-ietf-oauth-selective-disclosure-jwt-22.html#name-hash-function-claim\n */\nexport const sdJwtHashingAlgorithms: Array<Exclude<HashName, 'sha-1'>> = ['sha-256', 'sha-384', 'sha-512']\n\n/**\n * Get the hashing algorithm to use for the disclosure digests of an SD-JWT, defaulting to `sha-256`.\n *\n * The sign options already exclude insecure hashing algorithms on a type level, but this is\n * enforced at runtime as well, as the value can originate from JavaScript callers or dynamic input.\n */\nexport function getSdJwtHashingAlgorithm(hashingAlgorithm?: HashName): Exclude<HashName, 'sha-1'> {\n const hashAlg = hashingAlgorithm ?? 'sha-256'\n\n if (!sdJwtHashingAlgorithms.includes(hashAlg as Exclude<HashName, 'sha-1'>)) {\n throw new CredoError(\n `Unsupported hashing algorithm '${hashAlg}' for the disclosure digests of an SD-JWT. Supported hashing algorithms are ${sdJwtHashingAlgorithms.join(', ')}`\n )\n }\n\n return hashAlg as Exclude<HashName, 'sha-1'>\n}\n\nexport function getSdJwtSigner(agentContext: AgentContext, key: PublicJwk): Signer {\n const kms = agentContext.resolve(KeyManagementApi)\n\n return async (input: string) => {\n const result = await kms.sign({\n keyId: key.keyId,\n data: TypedArrayEncoder.fromUtf8String(input),\n algorithm: key.signatureAlgorithm,\n })\n\n return TypedArrayEncoder.toBase64Url(result.signature)\n }\n}\n\nexport function getSdJwtVerifier(agentContext: AgentContext, key: PublicJwk): Verifier {\n const kms = agentContext.resolve(KeyManagementApi)\n\n return async (message: string, signatureBase64Url: string) => {\n const result = await kms.verify({\n signature: TypedArrayEncoder.fromBase64Url(signatureBase64Url),\n key: {\n publicJwk: key.toJson(),\n },\n data: TypedArrayEncoder.fromUtf8String(message),\n algorithm: key.signatureAlgorithm,\n })\n\n return result.verified\n }\n}\n\nexport interface CnfPayload {\n jwk?: Jwk\n kid?: string\n}\n\nexport function parseHolderBindingFromCredential(payload?: Record<string, unknown>): SdJwtVcHolderBinding | null {\n if (!payload) {\n throw new CredoError('Unable to extract payload from SD-JWT VC')\n }\n\n if (!payload.cnf) {\n return null\n }\n const cnf: CnfPayload = payload.cnf\n\n if (cnf.jwk) {\n return {\n method: 'jwk',\n jwk: PublicJwk.fromUnknown(cnf.jwk),\n }\n }\n if (cnf.kid) {\n if (!cnf.kid.startsWith('did:') || !cnf.kid.includes('#')) {\n throw new CredoError('Invalid holder kid for did. Only absolute KIDs for cnf are supported')\n }\n return {\n method: 'did',\n didUrl: cnf.kid,\n }\n }\n\n throw new CredoError(\"Unsupported credential holder binding. Only 'did' and 'jwk' are supported at the moment.\")\n}\n\nexport function parseIssuerFromCredential(\n header?: Record<string, unknown>,\n payload?: Record<string, unknown>\n): SdJwtVcIssuer {\n if (!payload || !header) throw new SdJwtVcError('SD-JWT is missing payload')\n const iss = payload.iss as string | undefined\n\n if (header?.x5c) {\n if (!Array.isArray(header.x5c)) {\n throw new SdJwtVcError('Invalid x5c header in credential. Not an array.')\n }\n if (header.x5c.length === 0) {\n throw new SdJwtVcError('Invalid x5c header in credential. Empty array.')\n }\n if (header.x5c.some((x5c) => typeof x5c !== 'string')) {\n throw new SdJwtVcError('Invalid x5c header in credential. Not an array of strings.')\n }\n\n const certificateChain = header.x5c.map((cert) => X509Certificate.fromEncodedCertificate(cert))\n\n return {\n method: 'x5c',\n x5c: certificateChain,\n issuer: iss,\n }\n }\n\n if (iss?.startsWith('did:')) {\n // If `did` is used, we require a relative KID to be present to identify\n // the key used by issuer to sign the sd-jwt-vc\n if (!header.kid) {\n throw new SdJwtVcError('Credential does not contain a kid in the header')\n }\n\n const issuerKid = header.kid as string\n\n let didUrl: string\n if (issuerKid.startsWith('#')) {\n didUrl = `${iss}${issuerKid}`\n } else if (issuerKid.startsWith('did:')) {\n const didFromKid = parseDid(issuerKid)\n if (didFromKid.did !== iss) {\n throw new SdJwtVcError(\n `kid in header is an absolute DID URL, but the did (${didFromKid.did}) does not match with the 'iss' did (${iss})`\n )\n }\n\n didUrl = issuerKid\n } else {\n throw new SdJwtVcError(\n 'Invalid issuer kid for did. Only absolute or relative (starting with #) did urls are supported.'\n )\n }\n\n return {\n method: 'did',\n didUrl,\n }\n }\n\n throw new SdJwtVcError('Unsupported signing method for SD-JWT VC. Only did and x5c are supported at the moment.')\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"utils.mjs","names":[],"sources":["../../../src/modules/sd-jwt-vc/utils.ts"],"sourcesContent":["import type { Signer, Verifier } from '@sd-jwt/core'\nimport { AgentContext } from '../../agent'\nimport type { HashName } from '../../crypto'\nimport { CredoError } from '../../error'\nimport { TypedArrayEncoder } from '../../utils'\nimport { type DidPurpose, DidResolverService, DidsApi, getPublicJwkFromVerificationMethod, parseDid } from '../dids'\nimport { isKnownJwaSignatureAlgorithm, type Jwk, KeyManagementApi, PublicJwk } from '../kms'\nimport { X509Certificate } from '../x509/X509Certificate'\nimport { SdJwtVcError } from './SdJwtVcError'\nimport type { SdJwtVcHolderBinding, SdJwtVcIssuer } from './SdJwtVcOptions'\n\nexport async function resolveSigningPublicJwkFromDidUrl(agentContext: AgentContext, didUrl: string) {\n const dids = agentContext.dependencyManager.resolve(DidsApi)\n\n const { publicJwk } = await dids.resolveVerificationMethodFromCreatedDidRecord(didUrl)\n return publicJwk\n}\n\nexport async function resolveDidUrl(\n agentContext: AgentContext,\n didUrl: string,\n purposes: DidPurpose[] = ['assertionMethod']\n) {\n const didResolver = agentContext.dependencyManager.resolve(DidResolverService)\n const didDocument = await didResolver.resolveDidDocument(agentContext, didUrl)\n\n return {\n verificationMethod: didDocument.dereferenceKey(didUrl, purposes),\n didDocument,\n }\n}\n\nexport async function extractKeyFromHolderBinding(\n agentContext: AgentContext,\n holder: SdJwtVcHolderBinding,\n {\n forSigning = false,\n jwkKeyId,\n didPurposes,\n }: { forSigning?: boolean; jwkKeyId?: string; didPurposes?: DidPurpose[] } = {}\n) {\n if (holder.method === 'did') {\n const parsedDid = parseDid(holder.didUrl)\n if (!parsedDid.fragment) {\n throw new CredoError(`didUrl '${holder.didUrl}' does not contain a '#'. Unable to derive key from did document`)\n }\n\n let publicJwk: PublicJwk\n if (forSigning) {\n publicJwk = await resolveSigningPublicJwkFromDidUrl(agentContext, holder.didUrl)\n } else {\n const { verificationMethod } = await resolveDidUrl(agentContext, holder.didUrl, didPurposes)\n publicJwk = getPublicJwkFromVerificationMethod(verificationMethod)\n }\n\n const supportedSignatureAlgorithms = publicJwk.supportedSignatureAlgorithms\n if (supportedSignatureAlgorithms.length === 0) {\n throw new CredoError(`No supported JWA signature algorithms found for key ${publicJwk.jwkTypeHumanDescription}`)\n }\n const alg = supportedSignatureAlgorithms[0]\n\n return {\n alg,\n publicJwk,\n cnf: {\n // We need to include the whole didUrl here, otherwise the verifier\n // won't know which did it is associated with\n kid: holder.didUrl,\n },\n }\n }\n if (holder.method === 'jwk') {\n const publicJwk = holder.jwk\n const alg = publicJwk.supportedSignatureAlgorithms[0]\n\n if (forSigning) {\n publicJwk.keyId = jwkKeyId ?? publicJwk.legacyKeyId\n }\n\n return {\n alg,\n publicJwk,\n cnf: {\n jwk: publicJwk.toJson(),\n },\n }\n }\n\n throw new CredoError(\"Unsupported credential holder binding. Only 'did' and 'jwk' are supported at the moment.\")\n}\n\n/**\n * Set the `alg` from a JWT header on the public jwk, so signing and verification use the\n * algorithm of the JWT rather than the first supported signature algorithm of the key.\n *\n * Throws an error if the alg is not a known JWA signature algorithm, or if the alg is not\n * supported by the jwk.\n */\nexport function setJwkAlgFromJwtHeader(publicJwk: PublicJwk, jwtHeaderAlg: unknown) {\n if (typeof jwtHeaderAlg !== 'string' || !isKnownJwaSignatureAlgorithm(jwtHeaderAlg)) {\n throw new CredoError(`Expected JWT header 'alg' to be a known JWA signature algorithm, found '${jwtHeaderAlg}'`)\n }\n\n publicJwk.alg = jwtHeaderAlg\n}\n\n/**\n * Hashing algorithms that can be used for the disclosure digests of an SD-JWT, and are placed\n * in the `_sd_alg` claim.\n *\n * `sha-1` is omitted, as SD-JWT requires a hash algorithm that is considered secure at the\n * time of issuance.\n *\n * @see https://www.ietf.org/archive/id/draft-ietf-oauth-selective-disclosure-jwt-22.html#name-hash-function-claim\n */\nexport const sdJwtHashingAlgorithms: Array<Exclude<HashName, 'sha-1'>> = ['sha-256', 'sha-384', 'sha-512']\n\n/**\n * Get the hashing algorithm to use for the disclosure digests of an SD-JWT, defaulting to `sha-256`.\n *\n * The sign options already exclude insecure hashing algorithms on a type level, but this is\n * enforced at runtime as well, as the value can originate from JavaScript callers or dynamic input.\n */\nexport function getSdJwtHashingAlgorithm(hashingAlgorithm?: HashName): Exclude<HashName, 'sha-1'> {\n const hashAlg = hashingAlgorithm ?? 'sha-256'\n\n if (!sdJwtHashingAlgorithms.includes(hashAlg as Exclude<HashName, 'sha-1'>)) {\n throw new CredoError(\n `Unsupported hashing algorithm '${hashAlg}' for the disclosure digests of an SD-JWT. Supported hashing algorithms are ${sdJwtHashingAlgorithms.join(', ')}`\n )\n }\n\n return hashAlg as Exclude<HashName, 'sha-1'>\n}\n\nexport function getSdJwtSigner(agentContext: AgentContext, key: PublicJwk): Signer {\n const kms = agentContext.resolve(KeyManagementApi)\n\n return async (input: string) => {\n const result = await kms.sign({\n keyId: key.keyId,\n data: TypedArrayEncoder.fromUtf8String(input),\n algorithm: key.signatureAlgorithm,\n })\n\n return TypedArrayEncoder.toBase64Url(result.signature)\n }\n}\n\nexport function getSdJwtVerifier(agentContext: AgentContext, key: PublicJwk): Verifier {\n const kms = agentContext.resolve(KeyManagementApi)\n\n return async (message: string, signatureBase64Url: string) => {\n const result = await kms.verify({\n signature: TypedArrayEncoder.fromBase64Url(signatureBase64Url),\n key: {\n publicJwk: key.toJson(),\n },\n data: TypedArrayEncoder.fromUtf8String(message),\n algorithm: key.signatureAlgorithm,\n })\n\n return result.verified\n }\n}\n\nexport interface CnfPayload {\n jwk?: Jwk\n kid?: string\n}\n\nexport function parseHolderBindingFromCredential(payload?: Record<string, unknown>): SdJwtVcHolderBinding | null {\n if (!payload) {\n throw new CredoError('Unable to extract payload from SD-JWT VC')\n }\n\n if (!payload.cnf) {\n return null\n }\n const cnf: CnfPayload = payload.cnf\n\n if (cnf.jwk) {\n return {\n method: 'jwk',\n jwk: PublicJwk.fromUnknown(cnf.jwk),\n }\n }\n if (cnf.kid) {\n if (!cnf.kid.startsWith('did:') || !cnf.kid.includes('#')) {\n throw new CredoError('Invalid holder kid for did. Only absolute KIDs for cnf are supported')\n }\n return {\n method: 'did',\n didUrl: cnf.kid,\n }\n }\n\n throw new CredoError(\"Unsupported credential holder binding. Only 'did' and 'jwk' are supported at the moment.\")\n}\n\nexport function parseIssuerFromCredential(\n header?: Record<string, unknown>,\n payload?: Record<string, unknown>\n): SdJwtVcIssuer {\n if (!payload || !header) throw new SdJwtVcError('SD-JWT is missing payload')\n const iss = payload.iss as string | undefined\n\n if (header?.x5c) {\n if (!Array.isArray(header.x5c)) {\n throw new SdJwtVcError('Invalid x5c header in credential. Not an array.')\n }\n if (header.x5c.length === 0) {\n throw new SdJwtVcError('Invalid x5c header in credential. Empty array.')\n }\n if (header.x5c.some((x5c) => typeof x5c !== 'string')) {\n throw new SdJwtVcError('Invalid x5c header in credential. Not an array of strings.')\n }\n\n const certificateChain = header.x5c.map((cert) => X509Certificate.fromEncodedCertificate(cert))\n\n return {\n method: 'x5c',\n x5c: certificateChain,\n issuer: iss,\n }\n }\n\n if (iss?.startsWith('did:')) {\n // If `did` is used, we require a relative KID to be present to identify\n // the key used by issuer to sign the sd-jwt-vc\n if (!header.kid) {\n throw new SdJwtVcError('Credential does not contain a kid in the header')\n }\n\n const issuerKid = header.kid as string\n\n let didUrl: string\n if (issuerKid.startsWith('#')) {\n didUrl = `${iss}${issuerKid}`\n } else if (issuerKid.startsWith('did:')) {\n const didFromKid = parseDid(issuerKid)\n if (didFromKid.did !== iss) {\n throw new SdJwtVcError(\n `kid in header is an absolute DID URL, but the did (${didFromKid.did}) does not match with the 'iss' did (${iss})`\n )\n }\n\n didUrl = issuerKid\n } else {\n throw new SdJwtVcError(\n 'Invalid issuer kid for did. Only absolute or relative (starting with #) did urls are supported.'\n )\n }\n\n return {\n method: 'did',\n didUrl,\n }\n }\n\n throw new SdJwtVcError('Unsupported signing method for SD-JWT VC. Only did and x5c are supported at the moment.')\n}\n"],"mappings":"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"}
@@ -13,7 +13,7 @@ import { ProofPurpose } from "./linked-data-proofs/proof-purposes/ProofPurpose.m
13
13
  import "./linked-data-proofs/index.mjs";
14
14
  import { W3cCredentialRecord } from "./repository/W3cCredentialRecord.mjs";
15
15
  import "./repository/index.mjs";
16
- import { TrustedIssuerDid } from "../../agent/TrustedIssuersForVerification.mjs";
16
+ import { GetTrustedIssuersForCredential, TrustedIssuerDid } from "../../agent/TrustedIssuersForVerification.mjs";
17
17
  import "../kms/index.mjs";
18
18
  //#region src/modules/vc/W3cCredentialServiceOptions.d.ts
19
19
  export type W3cSignCredentialOptions<Format extends ClaimFormat.JwtVc | ClaimFormat.LdpVc | undefined = undefined> = Format extends ClaimFormat.JwtVc ? W3cJwtSignCredentialOptions : Format extends ClaimFormat.LdpVc ? W3cJsonLdSignCredentialOptions : W3cJwtSignCredentialOptions | W3cJsonLdSignCredentialOptions;
@@ -69,9 +69,9 @@ interface W3cVerifyCredentialOptionsBase {
69
69
  */
70
70
  verifyCredentialStatus?: boolean;
71
71
  /**
72
- * Trusted issuers for the verification.
72
+ * Trusted issuers for the verification, or a callback that resolves them for each credential.
73
73
  */
74
- trustedIssuers?: TrustedIssuerDid[];
74
+ trustedIssuers?: TrustedIssuerDid[] | GetTrustedIssuersForCredential;
75
75
  }
76
76
  export interface W3cJwtVerifyCredentialOptions extends W3cVerifyCredentialOptionsBase {
77
77
  credential: W3cJwtVerifiableCredential | string;
@@ -148,9 +148,9 @@ interface W3cVerifyPresentationOptionsBase {
148
148
  */
149
149
  verifyCredentialStatus?: boolean;
150
150
  /**
151
- * Trusted issuers for the verification.
151
+ * Trusted issuers for the verification, or a callback that resolves them for each credential.
152
152
  */
153
- trustedIssuers?: TrustedIssuerDid[];
153
+ trustedIssuers?: TrustedIssuerDid[] | GetTrustedIssuersForCredential;
154
154
  }
155
155
  export interface W3cJwtVerifyPresentationOptions extends W3cVerifyPresentationOptionsBase {
156
156
  presentation: W3cJwtVerifiablePresentation | string;
@@ -1 +1 @@
1
- {"version":3,"file":"W3cCredentialServiceOptions.d.mts","names":[],"sources":["../../../src/modules/vc/W3cCredentialServiceOptions.ts"],"mappings":";;;;;;;;;;;;;;;;;;YAWY,yBAAyB,eAAe,YAAY,QAAQ,YAAY,iCAClF,eAAe,YAAY,QACvB,8BACA,eAAe,YAAY,QACzB,iCACA,8BAA8B;YAC1B,2BAA2B,eAAe,YAAY,QAAQ,YAAY,iCACpF,eAAe,YAAY,QACvB,gCACA,eAAe,YAAY,QACzB,mCACA,gCAAgC;YAC5B,2BAA2B,eAAe,YAAY,QAAQ,YAAY,iCACpF,eAAe,YAAY,QACvB,gCACA,eAAe,YAAY,QACzB,mCACA,gCAAgC;YAC5B,+BAA+B,kCAAkC;UAEnE;;;;;;EAMR,QAAQ;;;;EAKR,YAAY;;;;;;EAOZ;;iBAGe,oCAAoC;EACnD,QAAQ,YAAY;;;;;;EAOpB,KAAK;;iBAGU,uCAAuC;;;;;EAKtD,QAAQ,YAAY;;;;;;EAOpB;EAEA,eAAe;EACf;;UAGQ;EACR;;;;EAKA;;;;EAKA,iBAAiB;;iBAGF,sCAAsC;EACrD,YAAY;;iBAGG,yCAAyC;EACxD,YAAY;EACZ,eAAe;;iBAGA;EACf,aAAa,cAAc;EAC3B;EACA;;UAGQ;;;;;;EAMR,QAAQ;;;;EAKR,cAAc;;;;;;EAOd;;;;EAKA;;;;EAKA;;iBAGe,yCAAyC;EACxD,QAAQ,YAAY;;;;;;EAOpB;EAEA,cAAc;;iBAGC,sCAAsC;EACrD,QAAQ,YAAY;;;;;;EAOpB,KAAK;;UAGG;;;;EAIR;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA,iBAAiB;;iBAGF,wCAAwC;EACvD,cAAc;;iBAGC,2CAA2C;EAC1D,cAAc;EACd,UAAU;;YAGA;EACV,QAAQ"}
1
+ {"version":3,"file":"W3cCredentialServiceOptions.d.mts","names":[],"sources":["../../../src/modules/vc/W3cCredentialServiceOptions.ts"],"mappings":";;;;;;;;;;;;;;;;;;YAWY,yBAAyB,eAAe,YAAY,QAAQ,YAAY,iCAClF,eAAe,YAAY,QACvB,8BACA,eAAe,YAAY,QACzB,iCACA,8BAA8B;YAC1B,2BAA2B,eAAe,YAAY,QAAQ,YAAY,iCACpF,eAAe,YAAY,QACvB,gCACA,eAAe,YAAY,QACzB,mCACA,gCAAgC;YAC5B,2BAA2B,eAAe,YAAY,QAAQ,YAAY,iCACpF,eAAe,YAAY,QACvB,gCACA,eAAe,YAAY,QACzB,mCACA,gCAAgC;YAC5B,+BAA+B,kCAAkC;UAEnE;;;;;;EAMR,QAAQ;;;;EAKR,YAAY;;;;;;EAOZ;;iBAGe,oCAAoC;EACnD,QAAQ,YAAY;;;;;;EAOpB,KAAK;;iBAGU,uCAAuC;;;;;EAKtD,QAAQ,YAAY;;;;;;EAOpB;EAEA,eAAe;EACf;;UAGQ;EACR;;;;EAKA;;;;EAKA,iBAAiB,qBAAqB;;iBAGvB,sCAAsC;EACrD,YAAY;;iBAGG,yCAAyC;EACxD,YAAY;EACZ,eAAe;;iBAGA;EACf,aAAa,cAAc;EAC3B;EACA;;UAGQ;;;;;;EAMR,QAAQ;;;;EAKR,cAAc;;;;;;EAOd;;;;EAKA;;;;EAKA;;iBAGe,yCAAyC;EACxD,QAAQ,YAAY;;;;;;EAOpB;EAEA,cAAc;;iBAGC,sCAAsC;EACrD,QAAQ,YAAY;;;;;;EAOpB,KAAK;;UAGG;;;;EAIR;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA,iBAAiB,qBAAqB;;iBAGvB,wCAAwC;EACvD,cAAc;;iBAGC,2CAA2C;EAC1D,cAAc;EACd,UAAU;;YAGA;EACV,QAAQ"}
@@ -71,11 +71,15 @@ export declare class W3cV2CredentialService {
71
71
  */
72
72
  verifyPresentation(agentContext: AgentContext, options: W3cV2VerifyPresentationOptions): Promise<W3cV2VerifyPresentationResult>;
73
73
  private verifyPresentationEntry;
74
+ /**
75
+ * A credential bound to a key with `cnf` must be presented with that key.
76
+ */
77
+ private verifyHolderBinding;
74
78
  private extractCredentialEntriesFromPresentation;
75
79
  private extractCredentialEntriesFromResolvedPresentation;
76
80
  private createInvalidCredentialEntryResult;
77
81
  private getClaimFormat;
78
- private mergeCredentialSubjectAuthenticationValidation;
82
+ private mergeHolderValidations;
79
83
  /**
80
84
  * Writes a credential to storage
81
85
  *
@@ -1 +1 @@
1
- {"version":3,"file":"W3cV2CredentialService.d.mts","names":[],"sources":["../../../src/modules/vc/W3cV2CredentialService.ts"],"mappings":";;;;;;;;;;;;;;;;;;qBAsDa;UACH;UACA;UACA;UACA;EAGN,YAAA,2BAA2B,2BAC3B,6BAA6B,6BAC7B,2BAA2B,2BAC3B,qCAAqC;;;;;;;EAc1B,eAAe,eAAe,YAAY,WAAW,YAAY,aAAa,YAAY,MACrG,cAAc,cACd,SAAS,2BAA2B,UACnC,QAAQ,0BAA0B;;;;EAsBxB,iBACX,cAAc,cACd,SAAS,+BACR,QAAQ;;;;;;;EAoCE,iBAAiB,eAAe,YAAY,WAAW,YAAY,aAAa,YAAY,MACvG,cAAc,cACd,SAAS,6BAA6B,UACrC,QAAQ,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgD1B,mBACX,cAAc,cACd,SAAS,iCACR,QAAQ;UAwHG;UAuEN;UASA;UAMA;UAQA;UAOA;;;;;;;EAmCK,gBACX,cAAc,cACd,SAAS,8BACR,QAAQ;EAOE,uBAAuB,cAAc,cAAc,aAAU;EAI7D,wBAAwB,cAAc,eAAe,QAAQ;EAI7D,wBAAwB,cAAc,cAAc,aAAa,QAAQ;EAIzE,uBACX,cAAc,cACd,OAAO,MAAM,wBACb,eAAe,eACd,QAAQ;EAKE,4BACX,cAAc,cACd,OAAO,MAAM,yBACZ,QAAQ"}
1
+ {"version":3,"file":"W3cV2CredentialService.d.mts","names":[],"sources":["../../../src/modules/vc/W3cV2CredentialService.ts"],"mappings":";;;;;;;;;;;;;;;;;;qBA2Da;UACH;UACA;UACA;UACA;EAGN,YAAA,2BAA2B,2BAC3B,6BAA6B,6BAC7B,2BAA2B,2BAC3B,qCAAqC;;;;;;;EAc1B,eAAe,eAAe,YAAY,WAAW,YAAY,aAAa,YAAY,MACrG,cAAc,cACd,SAAS,2BAA2B,UACnC,QAAQ,0BAA0B;;;;EAsBxB,iBACX,cAAc,cACd,SAAS,+BACR,QAAQ;;;;;;;EAoCE,iBAAiB,eAAe,YAAY,WAAW,YAAY,aAAa,YAAY,MACvG,cAAc,cACd,SAAS,6BAA6B,UACrC,QAAQ,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgD1B,mBACX,cAAc,cACd,SAAS,iCACR,QAAQ;UAkHG;;;;UA4FA;UA0BN;UASA;UAMA;UAQA;UAOA;;;;;;;EAuCK,gBACX,cAAc,cACd,SAAS,8BACR,QAAQ;EAOE,uBAAuB,cAAc,cAAc,aAAU;EAI7D,wBAAwB,cAAc,eAAe,QAAQ;EAI7D,wBAAwB,cAAc,cAAc,aAAa,QAAQ;EAIzE,uBACX,cAAc,cACd,OAAO,MAAM,wBACb,eAAe,eACd,QAAQ;EAKE,4BACX,cAAc,cACd,OAAO,MAAM,yBACZ,QAAQ"}