@sphereon/ssi-sdk.linked-vp 0.34.1-feature.SSISDK.82.linkedVP.328 → 0.34.1-feature.SSISDK.82.linkedVP.341
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.
- package/dist/index.cjs +27 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -5
- package/dist/index.d.ts +1 -5
- package/dist/index.js +27 -14
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
- package/src/__tests__/shared/linkedVPManagerAgentLogic.ts +15 -5
- package/src/agent/LinkedVPManager.ts +32 -16
- package/src/types/ILinkedVPManager.ts +1 -1
package/dist/index.cjs
CHANGED
|
@@ -354,10 +354,6 @@ var LinkedVPManager = class {
|
|
|
354
354
|
lvpGetServiceEntries: this.lvpGetServiceEntries.bind(this),
|
|
355
355
|
lvpGeneratePresentation: this.lvpGeneratePresentation.bind(this)
|
|
356
356
|
};
|
|
357
|
-
holderDids;
|
|
358
|
-
constructor(options) {
|
|
359
|
-
this.holderDids = options.holderDids;
|
|
360
|
-
}
|
|
361
357
|
async lvpPublishCredential(args, context) {
|
|
362
358
|
const { digitalCredentialId } = args;
|
|
363
359
|
const credential = await context.agent.crsGetCredential({
|
|
@@ -430,15 +426,17 @@ var LinkedVPManager = class {
|
|
|
430
426
|
filter
|
|
431
427
|
]
|
|
432
428
|
});
|
|
433
|
-
return credentials.filter((cred) => cred.linkedVpId !== void 0 && cred.linkedVpId !== null).
|
|
434
|
-
const
|
|
435
|
-
|
|
429
|
+
return credentials.filter((cred) => cred.linkedVpId !== void 0 && cred.linkedVpId !== null).flatMap((cred) => {
|
|
430
|
+
const uniformDocument = JSON.parse(cred.uniformDocument);
|
|
431
|
+
const holderDidForEntry = this.getHolderDid(uniformDocument);
|
|
432
|
+
return holderDidForEntry && holderDidForEntry.startsWith("did:web") ? [
|
|
433
|
+
this.credentialToServiceEntry(cred, holderDidForEntry)
|
|
434
|
+
] : [];
|
|
436
435
|
});
|
|
437
436
|
}
|
|
438
437
|
async lvpGeneratePresentation(args, context) {
|
|
439
438
|
const { linkedVpId } = args;
|
|
440
439
|
const tenantId = this.parseTenantFromLinkedVpId(linkedVpId);
|
|
441
|
-
const holderDid = this.getHolderDid(tenantId);
|
|
442
440
|
const uniqueCredentials = await context.agent.crsGetUniqueCredentials({
|
|
443
441
|
filter: [
|
|
444
442
|
{
|
|
@@ -455,14 +453,29 @@ var LinkedVPManager = class {
|
|
|
455
453
|
if (uniqueCredentials.length > 1) {
|
|
456
454
|
return Promise.reject(Error(`Multiple credentials found for linkedVpId ${linkedVpId}`));
|
|
457
455
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
456
|
+
const uniqueDigitalCredential = uniqueCredentials[0];
|
|
457
|
+
if (!uniqueDigitalCredential.uniformVerifiableCredential) {
|
|
458
|
+
return Promise.reject(Error(`uniformVerifiableCredential could not be found for credential ${uniqueDigitalCredential.digitalCredential.id}`));
|
|
459
|
+
}
|
|
460
|
+
const holderDid = this.getHolderDid(uniqueDigitalCredential.uniformVerifiableCredential);
|
|
462
461
|
if (!holderDid) {
|
|
463
|
-
|
|
462
|
+
return Promise.reject(Error(`Could not extract the holder did:web from cnf nor the credentialSubject id`));
|
|
463
|
+
}
|
|
464
|
+
return createLinkedVPPresentation(holderDid, uniqueDigitalCredential, context.agent);
|
|
465
|
+
}
|
|
466
|
+
getHolderDid(uniformDocument) {
|
|
467
|
+
if ("cnf" in uniformDocument && "jwk" in uniformDocument.cnf && "kid" in uniformDocument.cnf.jwk) {
|
|
468
|
+
return uniformDocument.cnf.jwk.kid.split("#")[0];
|
|
469
|
+
}
|
|
470
|
+
if ("credentialSubject" in uniformDocument) {
|
|
471
|
+
const credentialSubject = Array.isArray(uniformDocument.credentialSubject) ? uniformDocument.credentialSubject[0] : uniformDocument.credentialSubject;
|
|
472
|
+
if ("id" in credentialSubject && credentialSubject.id) {
|
|
473
|
+
if (credentialSubject.id.startsWith("did:web")) {
|
|
474
|
+
return credentialSubject.id;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
464
477
|
}
|
|
465
|
-
return
|
|
478
|
+
return void 0;
|
|
466
479
|
}
|
|
467
480
|
parseTenantFromLinkedVpId(linkedVpId) {
|
|
468
481
|
const idx = linkedVpId.lastIndexOf("@");
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../plugin.schema.json","../src/agent/LinkedVPManager.ts","../src/services/LinkedVPService.ts","../src/types/ILinkedVPManager.ts"],"sourcesContent":["/**\n * @public\n */\nimport schema from '../plugin.schema.json'\nexport { schema }\nexport { LinkedVPManager, linkedVPManagerMethods } from './agent/LinkedVPManager'\nexport * from './types/ILinkedVPManager'\n","{\n \"ILinkedVPManager\": {\n \"components\": {\n \"schemas\": {\n \"GeneratePresentationArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"linkedVpId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"linkedVpId\"\n ],\n \"additionalProperties\": false\n },\n \"LinkedVPPresentation\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"$ref\": \"#/components/schemas/Record<string,any>\"\n }\n ]\n },\n \"Record<string,any>\": {\n \"type\": \"object\"\n },\n \"GetServiceEntriesArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"tenantId\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"LinkedVPServiceEntry\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"const\": \"LinkedVerifiablePresentation\"\n },\n \"serviceEndpoint\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"serviceEndpoint\"\n ],\n \"additionalProperties\": false\n },\n \"HasLinkedVPEntryArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"linkedVpId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"linkedVpId\"\n ],\n \"additionalProperties\": false\n },\n \"PublishCredentialArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"digitalCredentialId\": {\n \"type\": \"string\"\n },\n \"linkedVpId\": {\n \"type\": \"string\"\n },\n \"tenantId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"digitalCredentialId\"\n ],\n \"additionalProperties\": false\n },\n \"LinkedVPEntry\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"linkedVpId\": {\n \"type\": \"string\"\n },\n \"tenantId\": {\n \"type\": \"string\"\n },\n \"linkedVpFrom\": {\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"createdAt\": {\n \"type\": \"string\",\n \"format\": \"date-time\"\n }\n },\n \"required\": [\n \"id\",\n \"linkedVpId\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"UnpublishCredentialArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"linkedVpId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"linkedVpId\"\n ],\n \"additionalProperties\": false\n }\n },\n \"methods\": {\n \"lvpGeneratePresentation\": {\n \"description\": \"Generate and return a Verifiable Presentation for a published LinkedVP This is the main endpoint handler for GET /linked-vp/\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/GeneratePresentationArgs\"\n },\n \"returnType\": {\n \"$ref\": \"#/components/schemas/LinkedVPPresentation\"\n }\n },\n \"lvpGetServiceEntries\": {\n \"description\": \"Get LinkedVP service entries for a DID to be added to a DID Document This is useful when generating DID Documents with toDidDocument\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/GetServiceEntriesArgs\"\n },\n \"returnType\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/LinkedVPServiceEntry\"\n }\n }\n },\n \"lvpHasEntry\": {\n \"description\": \"Check if a LinkedVP entry exists by linkedVpId\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/HasLinkedVPEntryArgs\"\n },\n \"returnType\": {\n \"type\": \"boolean\"\n }\n },\n \"lvpPublishCredential\": {\n \"description\": \"Publish a credential as a LinkedVP by adding it to the holder's DID Document\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/PublishCredentialArgs\"\n },\n \"returnType\": {\n \"$ref\": \"#/components/schemas/LinkedVPEntry\"\n }\n },\n \"lvpUnpublishCredential\": {\n \"description\": \"Unpublish a credential by removing its LinkedVP entry from the DID Document\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/UnpublishCredentialArgs\"\n },\n \"returnType\": {\n \"type\": \"boolean\"\n }\n }\n }\n }\n }\n}","import { DigitalCredential } from '@sphereon/ssi-sdk.data-store-types'\nimport { IAgentPlugin } from '@veramo/core'\nimport { IsNull, Not } from 'typeorm'\nimport { schema } from '../index'\nimport { createLinkedVPPresentation } from '../services/LinkedVPService'\nimport {\n GeneratePresentationArgs,\n GetServiceEntriesArgs,\n HasLinkedVPEntryArgs,\n ILinkedVPManager,\n LinkedVPEntry,\n LinkedVPPresentation,\n LinkedVPServiceEntry,\n PublishCredentialArgs,\n RequiredContext,\n UnpublishCredentialArgs,\n} from '../types'\n\n// Exposing the methods here for any REST implementation\nexport const linkedVPManagerMethods: Array<string> = [\n 'lvpPublishCredential',\n 'lvpUnpublishCredential',\n 'lvpHasEntry',\n 'lvpGetServiceEntries',\n 'lvpGeneratePresentation',\n]\n\n/**\n * {@inheritDoc ILinkedVPManager}\n */\nexport class LinkedVPManager implements IAgentPlugin {\n readonly schema = schema.ILinkedVPManager\n readonly methods: ILinkedVPManager = {\n lvpPublishCredential: this.lvpPublishCredential.bind(this),\n lvpUnpublishCredential: this.lvpUnpublishCredential.bind(this),\n lvpHasEntry: this.lvpHasEntry.bind(this),\n lvpGetServiceEntries: this.lvpGetServiceEntries.bind(this),\n lvpGeneratePresentation: this.lvpGeneratePresentation.bind(this),\n }\n\n private readonly holderDids: Record<string, string>\n\n constructor(options: { holderDids: Record<string, string> }) {\n this.holderDids = options.holderDids\n }\n\n private async lvpPublishCredential(args: PublishCredentialArgs, context: RequiredContext): Promise<LinkedVPEntry> {\n const { digitalCredentialId } = args\n\n const credential: DigitalCredential = await context.agent.crsGetCredential({ id: digitalCredentialId })\n\n if (credential.linkedVpId) {\n return Promise.reject(new Error(`Credential ${digitalCredentialId} is already published with linkedVpId ${credential.linkedVpId}`))\n }\n\n const linkedVpId = this.buildLinkedVpId(args.linkedVpId, credential.tenantId)\n\n await this.ensureLinkedVpIdUnique(linkedVpId, context, credential.tenantId)\n\n const publishedAt = new Date()\n await context.agent.crsUpdateCredential({\n id: digitalCredentialId,\n linkedVpId,\n linkedVpFrom: publishedAt,\n })\n\n return {\n id: credential.id,\n linkedVpId,\n tenantId: credential.tenantId,\n linkedVpFrom: publishedAt,\n createdAt: credential.createdAt,\n }\n }\n\n private async lvpUnpublishCredential(args: UnpublishCredentialArgs, context: RequiredContext): Promise<boolean> {\n const { linkedVpId } = args\n\n // Find credential by linkedVpId and tenantId\n const credentials = await context.agent.crsGetCredentials({\n filter: [{ linkedVpId }],\n })\n if (credentials.length === 0) {\n return Promise.reject(Error(`No credential found with linkedVpId ${linkedVpId}`))\n }\n\n const credential = credentials[0]\n await context.agent.crsUpdateCredential({\n id: credential.id,\n linkedVpId: undefined,\n linkedVpFrom: undefined,\n })\n\n return true\n }\n\n private async lvpHasEntry(args: HasLinkedVPEntryArgs, context: RequiredContext): Promise<boolean> {\n const { linkedVpId } = args\n\n try {\n const credentials = await context.agent.crsGetCredentials({\n filter: [{ linkedVpId }],\n })\n return credentials.length > 0\n } catch (error) {\n return false\n }\n }\n\n private async lvpGetServiceEntries(args: GetServiceEntriesArgs, context: RequiredContext): Promise<Array<LinkedVPServiceEntry>> {\n const { tenantId } = args\n\n // Get all published credentials (credentials with linkedVpId set)\n const filter: any = { linkedVpId: Not(IsNull()) }\n if (tenantId) {\n filter.tenantId = tenantId\n }\n\n const credentials = await context.agent.crsGetCredentials({\n filter: [filter],\n })\n\n return credentials\n .filter((cred) => cred.linkedVpId !== undefined && cred.linkedVpId !== null)\n .map((cred) => {\n const holderDidForEntry = this.getHolderDid(cred.tenantId)\n return this.credentialToServiceEntry(cred, holderDidForEntry)\n })\n }\n\n private async lvpGeneratePresentation(args: GeneratePresentationArgs, context: RequiredContext): Promise<LinkedVPPresentation> {\n const { linkedVpId } = args\n const tenantId = this.parseTenantFromLinkedVpId(linkedVpId)\n const holderDid = this.getHolderDid(tenantId)\n\n const uniqueCredentials = await context.agent.crsGetUniqueCredentials({\n filter: [\n {\n linkedVpId: args.linkedVpId,\n ...(tenantId && { tenantId }),\n },\n ],\n })\n if (uniqueCredentials.length === 0) {\n return Promise.reject(Error(`No published credentials found for linkedVpId ${linkedVpId}`))\n }\n if (uniqueCredentials.length > 1) {\n return Promise.reject(Error(`Multiple credentials found for linkedVpId ${linkedVpId}`))\n }\n\n // Generate the Verifiable Presentation with all published credentials\n return createLinkedVPPresentation(holderDid, uniqueCredentials[0], context.agent)\n }\n\n private getHolderDid(tenantId: string | undefined) {\n const holderDid = this.holderDids[tenantId ?? 'default']\n if (!holderDid) {\n throw Error(`No holder did supplied for tenant ${tenantId ?? 'default'}`)\n }\n return holderDid\n }\n\n private parseTenantFromLinkedVpId(linkedVpId: string): string | undefined {\n const idx = linkedVpId.lastIndexOf('@')\n return idx === -1 ? undefined : linkedVpId.substring(idx + 1)\n }\n\n private generateLinkedVpId(): string {\n return `lvp-${Math.random().toString(36).substring(2, 15)}`\n }\n\n private async ensureLinkedVpIdUnique(linkedVpId: string, context: RequiredContext, tenantId?: string): Promise<void> {\n const credentials = await context.agent.crsGetCredentials({\n filter: [{ linkedVpId, ...(tenantId && { tenantId }) }],\n })\n\n if (credentials.length > 0) {\n throw new Error(`LinkedVP ID ${linkedVpId} already exists${tenantId ? ` for tenant ${tenantId}` : ''}`)\n }\n }\n\n private buildLinkedVpId(linkedVpId: string | undefined, tenantId: string | undefined) {\n let finalLinkedVpId = linkedVpId || this.generateLinkedVpId()\n\n // Append tenantId if provided and not already present\n if (tenantId && tenantId !== '' && !finalLinkedVpId.includes('@')) {\n finalLinkedVpId = `${finalLinkedVpId}@${tenantId}`\n }\n return finalLinkedVpId\n }\n\n private getBaseUrlFromDid(holderDid: string): string {\n if (!holderDid.startsWith('did:web:')) {\n throw new Error(`Invalid DID: ${holderDid}, must be did:web`)\n }\n\n const withoutPrefix = holderDid.replace('did:web:', '') // example.com:tenants:tenant1\n const parts = withoutPrefix.split(':')\n const domain = parts.shift()! // example.com\n const path = parts.join('/') // tenants/tenant1\n\n return path\n ? `https://${domain}/${path}` // https://example.com/tenants/tenant1\n : `https://${domain}` // https://example.com\n }\n\n private buildServiceEndpoint(holderDid: string, linkedVpId: string): string {\n const baseUrl = this.getBaseUrlFromDid(holderDid)\n const cleanBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n return `${cleanBaseUrl}/linked-vp/${linkedVpId}`\n }\n\n private credentialToServiceEntry(credential: DigitalCredential, holderDid: string): LinkedVPServiceEntry {\n if (!credential.linkedVpId) {\n throw new Error(`Credential ${credential.id} does not have a linkedVpId`)\n }\n\n return {\n id: `${holderDid}#${credential.linkedVpId}`,\n type: 'LinkedVerifiablePresentation',\n serviceEndpoint: this.buildServiceEndpoint(holderDid, credential.linkedVpId),\n }\n }\n}\n","import { UniqueDigitalCredential } from '@sphereon/ssi-sdk.credential-store'\nimport { calculateSdHash, defaultGenerateDigest, PartialSdJwtKbJwt } from '@sphereon/ssi-sdk.sd-jwt'\n\nimport {\n CredentialMapper,\n DocumentFormat,\n Loggers,\n OriginalVerifiableCredential,\n SdJwtDecodedVerifiableCredential,\n WrappedVerifiableCredential,\n} from '@sphereon/ssi-types'\nimport { LinkedVPPresentation, LOGGER_NAMESPACE, RequiredContext } from '../types'\n\nconst logger = Loggers.DEFAULT.get(LOGGER_NAMESPACE)\nconst CLOCK_SKEW = 120 // TODO make adjustable?\n\n/**\n * Extracts the original credential from various wrapper types\n */\nfunction extractOriginalCredential(\n credential: UniqueDigitalCredential | WrappedVerifiableCredential | OriginalVerifiableCredential,\n): OriginalVerifiableCredential {\n if (typeof credential === 'string') {\n return credential\n }\n\n if ('digitalCredential' in credential) {\n const udc = credential as UniqueDigitalCredential\n if (udc.originalVerifiableCredential) {\n return udc.originalVerifiableCredential\n }\n return udc.uniformVerifiableCredential as OriginalVerifiableCredential\n }\n\n if ('original' in credential) {\n return credential.original\n }\n\n return credential as OriginalVerifiableCredential\n}\n\n/**\n * Creates a Verifiable Presentation for LinkedVP publishing\n * Contains multiple credentials in a single JWT VP\n * No nonce or audience since this is for publishing, not responding to verification\n */\nexport async function createLinkedVPPresentation(\n holderDid: string,\n credential: UniqueDigitalCredential,\n agent: RequiredContext['agent'],\n): Promise<LinkedVPPresentation> {\n logger.debug(`Creating LinkedVP presentation for ${holderDid} of credential ${credential.id}`)\n\n const identifier = await agent.identifierManagedGet({ identifier: holderDid })\n const originalCredential = extractOriginalCredential(credential)\n const documentFormat = CredentialMapper.detectDocumentType(originalCredential)\n switch (documentFormat) {\n case DocumentFormat.SD_JWT_VC: {\n // SD-JWT with KB-JWT\n const decodedSdJwt = await CredentialMapper.decodeSdJwtVcAsync(\n typeof originalCredential === 'string' ? originalCredential : (originalCredential as SdJwtDecodedVerifiableCredential).compactSdJwtVc,\n defaultGenerateDigest,\n )\n\n const hashAlg = decodedSdJwt.signedPayload._sd_alg ?? 'sha-256'\n const sdHash = calculateSdHash(decodedSdJwt.compactSdJwtVc, hashAlg, defaultGenerateDigest)\n const kbJwtPayload: PartialSdJwtKbJwt['payload'] = {\n iat: Math.floor(Date.now() / 1000 - CLOCK_SKEW),\n sd_hash: sdHash,\n }\n\n const presentationResult = await agent.createSdJwtPresentation({\n presentation: decodedSdJwt.compactSdJwtVc,\n kb: {\n payload: kbJwtPayload as any, // FIXME?\n },\n })\n\n return {\n documentFormat,\n presentationPayload: presentationResult.presentation,\n }\n }\n case DocumentFormat.JSONLD: {\n // JSON-LD VC - create JSON-LD VP with challenge and domain in proof\n const vcObject = typeof originalCredential === 'string' ? JSON.parse(originalCredential) : originalCredential\n\n const vpObject = {\n '@context': ['https://www.w3.org/2018/credentials/v1'],\n type: ['VerifiablePresentation'],\n verifiableCredential: [vcObject],\n holder: holderDid,\n }\n\n // Create JSON-LD VP with proof\n const verifiablePresentationSP = await agent.createVerifiablePresentation({\n presentation: vpObject,\n proofFormat: 'lds',\n keyRef: identifier.kmsKeyRef || identifier.kid,\n })\n return {\n documentFormat,\n presentationPayload: verifiablePresentationSP,\n }\n }\n case DocumentFormat.MSO_MDOC: {\n // ISO mdoc - create mdoc VP token\n // This is a placeholder implementation\n // Full implementation would require:\n // 1. Decode the mdoc using CredentialMapper or mdoc utilities\n // 2. Build proper mdoc VP token with session transcript\n // 3. Include nonce/audience in the session transcript\n logger.warning('mso_mdoc format has basic support - production use requires proper mdoc VP token implementation')\n\n return {\n documentFormat,\n presentationPayload: originalCredential,\n }\n }\n default: {\n // JWT VC - create JWT VP with nonce and aud in payload\n const vcJwt = typeof originalCredential === 'string' ? originalCredential : JSON.stringify(originalCredential)\n\n // Create VP JWT using agent method\n const vpPayload = {\n iss: holderDid,\n vp: {\n '@context': ['https://www.w3.org/2018/credentials/v1'],\n type: ['VerifiablePresentation'],\n holder: holderDid,\n verifiableCredential: [vcJwt],\n },\n iat: Math.floor(Date.now() / 1000 - CLOCK_SKEW),\n exp: Math.floor(Date.now() / 1000 + 600 + CLOCK_SKEW), // 10 minutes\n }\n\n // Use the agent's JWT creation capability\n const vpJwt = await agent.createVerifiablePresentation({\n presentation: vpPayload.vp,\n proofFormat: 'jwt',\n keyRef: identifier.kmsKeyRef || identifier.kid,\n })\n\n return {\n documentFormat,\n presentationPayload: (vpJwt.proof && 'jwt' in vpJwt.proof && vpJwt.proof.jwt) || vpJwt,\n }\n }\n }\n}\n","import { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'\nimport { ICredentialStore } from '@sphereon/ssi-sdk.credential-store'\nimport { VcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'\nimport { ISDJwtPlugin } from '@sphereon/ssi-sdk.sd-jwt'\nimport { DocumentFormat } from '@sphereon/ssi-types'\nimport { IAgentContext, IPluginMethodMap } from '@veramo/core'\nimport { IKeyManager } from '@veramo/core/src/types/IKeyManager'\n\nexport const LOGGER_NAMESPACE = 'sphereon:linked-vp'\n\nexport type LinkedVPPresentation = {\n documentFormat: DocumentFormat\n presentationPayload: string | Record<string, any>\n}\n\nexport interface ILinkedVPManager extends IPluginMethodMap {\n /**\n * Publish a credential as a LinkedVP by adding it to the holder's DID Document\n * @param args - Publication arguments including credential ID and scope configuration\n * @param context - Agent context\n */\n lvpPublishCredential(args: PublishCredentialArgs, context: RequiredContext): Promise<LinkedVPEntry>\n\n /**\n * Unpublish a credential by removing its LinkedVP entry from the DID Document\n * @param args - Unpublish arguments\n * @param context - Agent context\n */\n lvpUnpublishCredential(args: UnpublishCredentialArgs, context: RequiredContext): Promise<boolean>\n\n /**\n * Check if a LinkedVP entry exists by linkedVpId\n * @param args - Query arguments\n * @param context - Agent context\n */\n lvpHasEntry(args: HasLinkedVPEntryArgs, context: RequiredContext): Promise<boolean>\n\n /**\n * Get LinkedVP service entries for a DID to be added to a DID Document\n * This is useful when generating DID Documents with toDidDocument\n * @param args - Query arguments for the DID\n * @param context - Agent context\n */\n lvpGetServiceEntries(args: GetServiceEntriesArgs, context: RequiredContext): Promise<Array<LinkedVPServiceEntry>>\n\n /**\n * Generate and return a Verifiable Presentation for a published LinkedVP\n * This is the main endpoint handler for GET /linked-vp/{linkedVpId}\n * @param args - Generation arguments\n * @param context - Agent context\n */\n lvpGeneratePresentation(args: GeneratePresentationArgs, context: RequiredContext): Promise<LinkedVPPresentation>\n}\n\nexport type PublishCredentialArgs = {\n digitalCredentialId: string\n linkedVpId?: string // Optional: if not provided, will be auto-generated\n}\n\nexport type UnpublishCredentialArgs = {\n linkedVpId: string\n}\n\nexport type HasLinkedVPEntryArgs = {\n linkedVpId: string\n}\n\nexport type GetServiceEntriesArgs = {\n tenantId?: string\n}\n\nexport type GeneratePresentationArgs = {\n linkedVpId: string\n}\n\nexport type LinkedVPEntry = {\n id: string\n linkedVpId: string\n tenantId?: string\n linkedVpFrom?: Date\n createdAt: Date\n}\n\nexport type LinkedVPServiceEntry = {\n id: string\n type: 'LinkedVerifiablePresentation'\n serviceEndpoint: string\n}\n\nexport type RequiredContext = IAgentContext<IIdentifierResolution & ICredentialStore & IKeyManager & VcdmCredentialPlugin & ISDJwtPlugin>\n"],"mappings":"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","names":["LOGGER_NAMESPACE","logger","Loggers","DEFAULT","get","LOGGER_NAMESPACE","CLOCK_SKEW","extractOriginalCredential","credential","udc","originalVerifiableCredential","uniformVerifiableCredential","original","createLinkedVPPresentation","holderDid","agent","debug","id","identifier","identifierManagedGet","originalCredential","documentFormat","CredentialMapper","detectDocumentType","DocumentFormat","SD_JWT_VC","decodedSdJwt","decodeSdJwtVcAsync","compactSdJwtVc","defaultGenerateDigest","hashAlg","signedPayload","_sd_alg","sdHash","calculateSdHash","kbJwtPayload","iat","Math","floor","Date","now","sd_hash","presentationResult","createSdJwtPresentation","presentation","kb","payload","presentationPayload","JSONLD","vcObject","JSON","parse","vpObject","type","verifiableCredential","holder","verifiablePresentationSP","createVerifiablePresentation","proofFormat","keyRef","kmsKeyRef","kid","MSO_MDOC","warning","vcJwt","stringify","vpPayload","iss","vp","exp","vpJwt","proof","jwt","linkedVPManagerMethods","LinkedVPManager","schema","ILinkedVPManager","methods","lvpPublishCredential","bind","lvpUnpublishCredential","lvpHasEntry","lvpGetServiceEntries","lvpGeneratePresentation","holderDids","options","args","context","digitalCredentialId","credential","agent","crsGetCredential","id","linkedVpId","Promise","reject","Error","buildLinkedVpId","tenantId","ensureLinkedVpIdUnique","publishedAt","Date","crsUpdateCredential","linkedVpFrom","createdAt","credentials","crsGetCredentials","filter","length","undefined","error","Not","IsNull","cred","map","holderDidForEntry","getHolderDid","credentialToServiceEntry","parseTenantFromLinkedVpId","holderDid","uniqueCredentials","crsGetUniqueCredentials","createLinkedVPPresentation","idx","lastIndexOf","substring","generateLinkedVpId","Math","random","toString","finalLinkedVpId","includes","getBaseUrlFromDid","startsWith","withoutPrefix","replace","parts","split","domain","shift","path","join","buildServiceEndpoint","baseUrl","cleanBaseUrl","endsWith","slice","type","serviceEndpoint"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../plugin.schema.json","../src/agent/LinkedVPManager.ts","../src/services/LinkedVPService.ts","../src/types/ILinkedVPManager.ts"],"sourcesContent":["/**\n * @public\n */\nimport schema from '../plugin.schema.json'\nexport { schema }\nexport { LinkedVPManager, linkedVPManagerMethods } from './agent/LinkedVPManager'\nexport * from './types/ILinkedVPManager'\n","{\n \"ILinkedVPManager\": {\n \"components\": {\n \"schemas\": {\n \"GeneratePresentationArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"linkedVpId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"linkedVpId\"\n ],\n \"additionalProperties\": false\n },\n \"LinkedVPPresentation\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"$ref\": \"#/components/schemas/Record<string,any>\"\n }\n ]\n },\n \"Record<string,any>\": {\n \"type\": \"object\"\n },\n \"GetServiceEntriesArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"tenantId\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"LinkedVPServiceEntry\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"const\": \"LinkedVerifiablePresentation\"\n },\n \"serviceEndpoint\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"serviceEndpoint\"\n ],\n \"additionalProperties\": false\n },\n \"HasLinkedVPEntryArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"linkedVpId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"linkedVpId\"\n ],\n \"additionalProperties\": false\n },\n \"PublishCredentialArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"digitalCredentialId\": {\n \"type\": \"string\"\n },\n \"linkedVpId\": {\n \"type\": \"string\"\n },\n \"tenantId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"digitalCredentialId\"\n ],\n \"additionalProperties\": false\n },\n \"LinkedVPEntry\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"linkedVpId\": {\n \"type\": \"string\"\n },\n \"tenantId\": {\n \"type\": \"string\"\n },\n \"linkedVpFrom\": {\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"createdAt\": {\n \"type\": \"string\",\n \"format\": \"date-time\"\n }\n },\n \"required\": [\n \"id\",\n \"linkedVpId\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"UnpublishCredentialArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"linkedVpId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"linkedVpId\"\n ],\n \"additionalProperties\": false\n }\n },\n \"methods\": {\n \"lvpGeneratePresentation\": {\n \"description\": \"Generate and return a Verifiable Presentation for a published LinkedVP This is the main endpoint handler for GET /linked-vp/\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/GeneratePresentationArgs\"\n },\n \"returnType\": {\n \"$ref\": \"#/components/schemas/LinkedVPPresentation\"\n }\n },\n \"lvpGetServiceEntries\": {\n \"description\": \"Get LinkedVP service entries for a DID to be added to a DID Document This is useful when generating DID Documents with toDidDocument\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/GetServiceEntriesArgs\"\n },\n \"returnType\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/LinkedVPServiceEntry\"\n }\n }\n },\n \"lvpHasEntry\": {\n \"description\": \"Check if a LinkedVP entry exists by linkedVpId\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/HasLinkedVPEntryArgs\"\n },\n \"returnType\": {\n \"type\": \"boolean\"\n }\n },\n \"lvpPublishCredential\": {\n \"description\": \"Publish a credential as a LinkedVP by adding it to the holder's DID Document\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/PublishCredentialArgs\"\n },\n \"returnType\": {\n \"$ref\": \"#/components/schemas/LinkedVPEntry\"\n }\n },\n \"lvpUnpublishCredential\": {\n \"description\": \"Unpublish a credential by removing its LinkedVP entry from the DID Document\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/UnpublishCredentialArgs\"\n },\n \"returnType\": {\n \"type\": \"boolean\"\n }\n }\n }\n }\n }\n}","import { DigitalCredential } from '@sphereon/ssi-sdk.data-store-types'\nimport { type IVerifiableCredential } from '@sphereon/ssi-types'\nimport { IAgentPlugin } from '@veramo/core'\nimport { IsNull, Not } from 'typeorm'\nimport { schema } from '../index'\nimport { createLinkedVPPresentation } from '../services/LinkedVPService'\nimport {\n GeneratePresentationArgs,\n GetServiceEntriesArgs,\n HasLinkedVPEntryArgs,\n ILinkedVPManager,\n LinkedVPEntry,\n LinkedVPPresentation,\n LinkedVPServiceEntry,\n PublishCredentialArgs,\n RequiredContext,\n UnpublishCredentialArgs,\n} from '../types'\n\n// Exposing the methods here for any REST implementation\nexport const linkedVPManagerMethods: Array<string> = [\n 'lvpPublishCredential',\n 'lvpUnpublishCredential',\n 'lvpHasEntry',\n 'lvpGetServiceEntries',\n 'lvpGeneratePresentation',\n]\n\n/**\n * {@inheritDoc ILinkedVPManager}\n */\nexport class LinkedVPManager implements IAgentPlugin {\n readonly schema = schema.ILinkedVPManager\n readonly methods: ILinkedVPManager = {\n lvpPublishCredential: this.lvpPublishCredential.bind(this),\n lvpUnpublishCredential: this.lvpUnpublishCredential.bind(this),\n lvpHasEntry: this.lvpHasEntry.bind(this),\n lvpGetServiceEntries: this.lvpGetServiceEntries.bind(this),\n lvpGeneratePresentation: this.lvpGeneratePresentation.bind(this),\n }\n\n private async lvpPublishCredential(args: PublishCredentialArgs, context: RequiredContext): Promise<LinkedVPEntry> {\n const { digitalCredentialId } = args\n\n const credential: DigitalCredential = await context.agent.crsGetCredential({ id: digitalCredentialId })\n\n if (credential.linkedVpId) {\n return Promise.reject(new Error(`Credential ${digitalCredentialId} is already published with linkedVpId ${credential.linkedVpId}`))\n }\n\n const linkedVpId = this.buildLinkedVpId(args.linkedVpId, credential.tenantId)\n\n await this.ensureLinkedVpIdUnique(linkedVpId, context, credential.tenantId)\n\n const publishedAt = new Date()\n await context.agent.crsUpdateCredential({\n id: digitalCredentialId,\n linkedVpId,\n linkedVpFrom: publishedAt,\n })\n\n return {\n id: credential.id,\n linkedVpId,\n tenantId: credential.tenantId,\n linkedVpFrom: publishedAt,\n createdAt: credential.createdAt,\n }\n }\n\n private async lvpUnpublishCredential(args: UnpublishCredentialArgs, context: RequiredContext): Promise<boolean> {\n const { linkedVpId } = args\n\n // Find credential by linkedVpId and tenantId\n const credentials = await context.agent.crsGetCredentials({\n filter: [{ linkedVpId }],\n })\n if (credentials.length === 0) {\n return Promise.reject(Error(`No credential found with linkedVpId ${linkedVpId}`))\n }\n\n const credential = credentials[0]\n await context.agent.crsUpdateCredential({\n id: credential.id,\n linkedVpId: undefined,\n linkedVpFrom: undefined,\n })\n\n return true\n }\n\n private async lvpHasEntry(args: HasLinkedVPEntryArgs, context: RequiredContext): Promise<boolean> {\n const { linkedVpId } = args\n\n try {\n const credentials = await context.agent.crsGetCredentials({\n filter: [{ linkedVpId }],\n })\n return credentials.length > 0\n } catch (error) {\n return false\n }\n }\n\n private async lvpGetServiceEntries(args: GetServiceEntriesArgs, context: RequiredContext): Promise<Array<LinkedVPServiceEntry>> {\n const { tenantId } = args\n\n // Get all published credentials (credentials with linkedVpId set)\n const filter: any = { linkedVpId: Not(IsNull()) }\n if (tenantId) {\n filter.tenantId = tenantId\n }\n\n const credentials = await context.agent.crsGetCredentials({\n filter: [filter],\n })\n\n return credentials\n .filter((cred) => cred.linkedVpId !== undefined && cred.linkedVpId !== null)\n .flatMap((cred) => {\n const uniformDocument = JSON.parse(cred.uniformDocument) as IVerifiableCredential\n const holderDidForEntry = this.getHolderDid(uniformDocument)\n return holderDidForEntry && holderDidForEntry.startsWith('did:web') ? [this.credentialToServiceEntry(cred, holderDidForEntry)] : []\n })\n }\n\n private async lvpGeneratePresentation(args: GeneratePresentationArgs, context: RequiredContext): Promise<LinkedVPPresentation> {\n const { linkedVpId } = args\n const tenantId = this.parseTenantFromLinkedVpId(linkedVpId)\n\n const uniqueCredentials = await context.agent.crsGetUniqueCredentials({\n filter: [\n {\n linkedVpId: args.linkedVpId,\n ...(tenantId && { tenantId }),\n },\n ],\n })\n if (uniqueCredentials.length === 0) {\n return Promise.reject(Error(`No published credentials found for linkedVpId ${linkedVpId}`))\n }\n if (uniqueCredentials.length > 1) {\n return Promise.reject(Error(`Multiple credentials found for linkedVpId ${linkedVpId}`))\n }\n\n const uniqueDigitalCredential = uniqueCredentials[0]\n if (!uniqueDigitalCredential.uniformVerifiableCredential) {\n return Promise.reject(Error(`uniformVerifiableCredential could not be found for credential ${uniqueDigitalCredential.digitalCredential.id}`))\n }\n const holderDid = this.getHolderDid(uniqueDigitalCredential.uniformVerifiableCredential)\n if (!holderDid) {\n return Promise.reject(Error(`Could not extract the holder did:web from cnf nor the credentialSubject id`))\n }\n\n // Generate the Verifiable Presentation with all published credentials\n return createLinkedVPPresentation(holderDid, uniqueDigitalCredential, context.agent)\n }\n\n private getHolderDid(uniformDocument: IVerifiableCredential): string | undefined {\n // Determine holder DID for identifier resolution\n if ('cnf' in uniformDocument && 'jwk' in uniformDocument.cnf && 'kid' in uniformDocument.cnf.jwk) {\n return uniformDocument.cnf.jwk.kid.split('#')[0]\n }\n\n if ('credentialSubject' in uniformDocument) {\n const credentialSubject = Array.isArray(uniformDocument.credentialSubject)\n ? uniformDocument.credentialSubject[0]\n : uniformDocument.credentialSubject\n if ('id' in credentialSubject && credentialSubject.id) {\n if (credentialSubject.id.startsWith('did:web')) {\n return credentialSubject.id\n }\n }\n }\n\n return undefined\n }\n\n private parseTenantFromLinkedVpId(linkedVpId: string): string | undefined {\n const idx = linkedVpId.lastIndexOf('@')\n return idx === -1 ? undefined : linkedVpId.substring(idx + 1)\n }\n\n private generateLinkedVpId(): string {\n return `lvp-${Math.random().toString(36).substring(2, 15)}`\n }\n\n private async ensureLinkedVpIdUnique(linkedVpId: string, context: RequiredContext, tenantId?: string): Promise<void> {\n const credentials = await context.agent.crsGetCredentials({\n filter: [{ linkedVpId, ...(tenantId && { tenantId }) }],\n })\n\n if (credentials.length > 0) {\n throw new Error(`LinkedVP ID ${linkedVpId} already exists${tenantId ? ` for tenant ${tenantId}` : ''}`)\n }\n }\n\n private buildLinkedVpId(linkedVpId: string | undefined, tenantId: string | undefined) {\n let finalLinkedVpId = linkedVpId || this.generateLinkedVpId()\n\n // Append tenantId if provided and not already present\n if (tenantId && tenantId !== '' && !finalLinkedVpId.includes('@')) {\n finalLinkedVpId = `${finalLinkedVpId}@${tenantId}`\n }\n return finalLinkedVpId\n }\n\n private getBaseUrlFromDid(holderDid: string): string {\n if (!holderDid.startsWith('did:web:')) {\n throw new Error(`Invalid DID: ${holderDid}, must be did:web`)\n }\n\n const withoutPrefix = holderDid.replace('did:web:', '') // example.com:tenants:tenant1\n const parts = withoutPrefix.split(':')\n const domain = parts.shift()! // example.com\n const path = parts.join('/') // tenants/tenant1\n\n return path\n ? `https://${domain}/${path}` // https://example.com/tenants/tenant1\n : `https://${domain}` // https://example.com\n }\n\n private buildServiceEndpoint(holderDid: string, linkedVpId: string): string {\n const baseUrl = this.getBaseUrlFromDid(holderDid)\n const cleanBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n return `${cleanBaseUrl}/linked-vp/${linkedVpId}`\n }\n\n private credentialToServiceEntry(credential: DigitalCredential, holderDid: string): LinkedVPServiceEntry {\n if (!credential.linkedVpId) {\n throw new Error(`Credential ${credential.id} does not have a linkedVpId`)\n }\n\n return {\n id: `${holderDid}#${credential.linkedVpId}`,\n type: 'LinkedVerifiablePresentation',\n serviceEndpoint: this.buildServiceEndpoint(holderDid, credential.linkedVpId),\n }\n }\n}\n","import { UniqueDigitalCredential } from '@sphereon/ssi-sdk.credential-store'\nimport { calculateSdHash, defaultGenerateDigest, PartialSdJwtKbJwt } from '@sphereon/ssi-sdk.sd-jwt'\n\nimport {\n CredentialMapper,\n DocumentFormat,\n Loggers,\n OriginalVerifiableCredential,\n SdJwtDecodedVerifiableCredential,\n WrappedVerifiableCredential,\n} from '@sphereon/ssi-types'\nimport { LinkedVPPresentation, LOGGER_NAMESPACE, RequiredContext } from '../types'\n\nconst logger = Loggers.DEFAULT.get(LOGGER_NAMESPACE)\nconst CLOCK_SKEW = 120 // TODO make adjustable?\n\n/**\n * Extracts the original credential from various wrapper types\n */\nfunction extractOriginalCredential(\n credential: UniqueDigitalCredential | WrappedVerifiableCredential | OriginalVerifiableCredential,\n): OriginalVerifiableCredential {\n if (typeof credential === 'string') {\n return credential\n }\n\n if ('digitalCredential' in credential) {\n const udc = credential as UniqueDigitalCredential\n if (udc.originalVerifiableCredential) {\n return udc.originalVerifiableCredential\n }\n return udc.uniformVerifiableCredential as OriginalVerifiableCredential\n }\n\n if ('original' in credential) {\n return credential.original\n }\n\n return credential as OriginalVerifiableCredential\n}\n\n/**\n * Creates a Verifiable Presentation for LinkedVP publishing\n * Contains multiple credentials in a single JWT VP\n * No nonce or audience since this is for publishing, not responding to verification\n */\nexport async function createLinkedVPPresentation(\n holderDid: string,\n credential: UniqueDigitalCredential,\n agent: RequiredContext['agent'],\n): Promise<LinkedVPPresentation> {\n logger.debug(`Creating LinkedVP presentation for ${holderDid} of credential ${credential.id}`)\n\n const identifier = await agent.identifierManagedGet({ identifier: holderDid })\n const originalCredential = extractOriginalCredential(credential)\n const documentFormat = CredentialMapper.detectDocumentType(originalCredential)\n switch (documentFormat) {\n case DocumentFormat.SD_JWT_VC: {\n // SD-JWT with KB-JWT\n const decodedSdJwt = await CredentialMapper.decodeSdJwtVcAsync(\n typeof originalCredential === 'string' ? originalCredential : (originalCredential as SdJwtDecodedVerifiableCredential).compactSdJwtVc,\n defaultGenerateDigest,\n )\n\n const hashAlg = decodedSdJwt.signedPayload._sd_alg ?? 'sha-256'\n const sdHash = calculateSdHash(decodedSdJwt.compactSdJwtVc, hashAlg, defaultGenerateDigest)\n const kbJwtPayload: PartialSdJwtKbJwt['payload'] = {\n iat: Math.floor(Date.now() / 1000 - CLOCK_SKEW),\n sd_hash: sdHash,\n }\n\n const presentationResult = await agent.createSdJwtPresentation({\n presentation: decodedSdJwt.compactSdJwtVc,\n kb: {\n payload: kbJwtPayload as any, // FIXME?\n },\n })\n\n return {\n documentFormat,\n presentationPayload: presentationResult.presentation,\n }\n }\n case DocumentFormat.JSONLD: {\n // JSON-LD VC - create JSON-LD VP with challenge and domain in proof\n const vcObject = typeof originalCredential === 'string' ? JSON.parse(originalCredential) : originalCredential\n\n const vpObject = {\n '@context': ['https://www.w3.org/2018/credentials/v1'],\n type: ['VerifiablePresentation'],\n verifiableCredential: [vcObject],\n holder: holderDid,\n }\n\n // Create JSON-LD VP with proof\n const verifiablePresentationSP = await agent.createVerifiablePresentation({\n presentation: vpObject,\n proofFormat: 'lds',\n keyRef: identifier.kmsKeyRef || identifier.kid,\n })\n return {\n documentFormat,\n presentationPayload: verifiablePresentationSP,\n }\n }\n case DocumentFormat.MSO_MDOC: {\n // ISO mdoc - create mdoc VP token\n // This is a placeholder implementation\n // Full implementation would require:\n // 1. Decode the mdoc using CredentialMapper or mdoc utilities\n // 2. Build proper mdoc VP token with session transcript\n // 3. Include nonce/audience in the session transcript\n logger.warning('mso_mdoc format has basic support - production use requires proper mdoc VP token implementation')\n\n return {\n documentFormat,\n presentationPayload: originalCredential,\n }\n }\n default: {\n // JWT VC - create JWT VP with nonce and aud in payload\n const vcJwt = typeof originalCredential === 'string' ? originalCredential : JSON.stringify(originalCredential)\n\n // Create VP JWT using agent method\n const vpPayload = {\n iss: holderDid,\n vp: {\n '@context': ['https://www.w3.org/2018/credentials/v1'],\n type: ['VerifiablePresentation'],\n holder: holderDid,\n verifiableCredential: [vcJwt],\n },\n iat: Math.floor(Date.now() / 1000 - CLOCK_SKEW),\n exp: Math.floor(Date.now() / 1000 + 600 + CLOCK_SKEW), // 10 minutes\n }\n\n // Use the agent's JWT creation capability\n const vpJwt = await agent.createVerifiablePresentation({\n presentation: vpPayload.vp,\n proofFormat: 'jwt',\n keyRef: identifier.kmsKeyRef || identifier.kid,\n })\n\n return {\n documentFormat,\n presentationPayload: (vpJwt.proof && 'jwt' in vpJwt.proof && vpJwt.proof.jwt) || vpJwt,\n }\n }\n }\n}\n","import { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'\nimport { ICredentialStore } from '@sphereon/ssi-sdk.credential-store'\nimport { VcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'\nimport { ISDJwtPlugin } from '@sphereon/ssi-sdk.sd-jwt'\nimport { DocumentFormat } from '@sphereon/ssi-types'\nimport { IAgentContext, IPluginMethodMap } from '@veramo/core'\nimport { IKeyManager } from '@veramo/core/src/types/IKeyManager'\n\nexport const LOGGER_NAMESPACE = 'sphereon:linked-vp'\n\nexport type LinkedVPPresentation = {\n documentFormat: DocumentFormat\n presentationPayload: string | Record<string, any>\n}\n\nexport interface ILinkedVPManager extends IPluginMethodMap {\n /**\n * Publish a credential as a LinkedVP by adding it to the holder's DID Document\n * @param args - Publication arguments including credential ID and scope configuration\n * @param context - Agent context\n */\n lvpPublishCredential(args: PublishCredentialArgs, context: RequiredContext): Promise<LinkedVPEntry>\n\n /**\n * Unpublish a credential by removing its LinkedVP entry from the DID Document\n * @param args - Unpublish arguments\n * @param context - Agent context\n */\n lvpUnpublishCredential(args: UnpublishCredentialArgs, context: RequiredContext): Promise<boolean>\n\n /**\n * Check if a LinkedVP entry exists by linkedVpId\n * @param args - Query arguments\n * @param context - Agent context\n */\n lvpHasEntry(args: HasLinkedVPEntryArgs, context: RequiredContext): Promise<boolean>\n\n /**\n * Get LinkedVP service entries for a DID to be added to a DID Document\n * This is useful when generating DID Documents with toDidDocument\n * @param args - Query arguments for the DID\n * @param context - Agent context\n */\n lvpGetServiceEntries(args: GetServiceEntriesArgs, context: RequiredContext): Promise<Array<LinkedVPServiceEntry>>\n\n /**\n * Generate and return a Verifiable Presentation for a published LinkedVP\n * This is the main endpoint handler for GET /linked-vp/{linkedVpId}\n * @param args - Generation arguments\n * @param context - Agent context\n */\n lvpGeneratePresentation(args: GeneratePresentationArgs, context: RequiredContext): Promise<LinkedVPPresentation>\n}\n\nexport type PublishCredentialArgs = {\n digitalCredentialId: string\n linkedVpId?: string // Optional: if not provided, will be auto-generated\n}\n\nexport type UnpublishCredentialArgs = {\n linkedVpId: string\n}\n\nexport type HasLinkedVPEntryArgs = {\n linkedVpId: string\n}\n\nexport type GetServiceEntriesArgs = {\n tenantId?: string\n}\n\nexport type GeneratePresentationArgs = {\n linkedVpId: string\n}\n\nexport type LinkedVPEntry = {\n id: string\n linkedVpId: string\n linkedVpFrom?: Date\n tenantId?: string\n createdAt: Date\n}\n\nexport type LinkedVPServiceEntry = {\n id: string\n type: 'LinkedVerifiablePresentation'\n serviceEndpoint: string\n}\n\nexport type RequiredContext = IAgentContext<IIdentifierResolution & ICredentialStore & IKeyManager & VcdmCredentialPlugin & ISDJwtPlugin>\n"],"mappings":"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","names":["LOGGER_NAMESPACE","logger","Loggers","DEFAULT","get","LOGGER_NAMESPACE","CLOCK_SKEW","extractOriginalCredential","credential","udc","originalVerifiableCredential","uniformVerifiableCredential","original","createLinkedVPPresentation","holderDid","agent","debug","id","identifier","identifierManagedGet","originalCredential","documentFormat","CredentialMapper","detectDocumentType","DocumentFormat","SD_JWT_VC","decodedSdJwt","decodeSdJwtVcAsync","compactSdJwtVc","defaultGenerateDigest","hashAlg","signedPayload","_sd_alg","sdHash","calculateSdHash","kbJwtPayload","iat","Math","floor","Date","now","sd_hash","presentationResult","createSdJwtPresentation","presentation","kb","payload","presentationPayload","JSONLD","vcObject","JSON","parse","vpObject","type","verifiableCredential","holder","verifiablePresentationSP","createVerifiablePresentation","proofFormat","keyRef","kmsKeyRef","kid","MSO_MDOC","warning","vcJwt","stringify","vpPayload","iss","vp","exp","vpJwt","proof","jwt","linkedVPManagerMethods","LinkedVPManager","schema","ILinkedVPManager","methods","lvpPublishCredential","bind","lvpUnpublishCredential","lvpHasEntry","lvpGetServiceEntries","lvpGeneratePresentation","args","context","digitalCredentialId","credential","agent","crsGetCredential","id","linkedVpId","Promise","reject","Error","buildLinkedVpId","tenantId","ensureLinkedVpIdUnique","publishedAt","Date","crsUpdateCredential","linkedVpFrom","createdAt","credentials","crsGetCredentials","filter","length","undefined","error","Not","IsNull","cred","flatMap","uniformDocument","JSON","parse","holderDidForEntry","getHolderDid","startsWith","credentialToServiceEntry","parseTenantFromLinkedVpId","uniqueCredentials","crsGetUniqueCredentials","uniqueDigitalCredential","uniformVerifiableCredential","digitalCredential","holderDid","createLinkedVPPresentation","cnf","jwk","kid","split","credentialSubject","Array","isArray","idx","lastIndexOf","substring","generateLinkedVpId","Math","random","toString","finalLinkedVpId","includes","getBaseUrlFromDid","withoutPrefix","replace","parts","domain","shift","path","join","buildServiceEndpoint","baseUrl","cleanBaseUrl","endsWith","slice","type","serviceEndpoint"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -249,8 +249,8 @@ type GeneratePresentationArgs = {
|
|
|
249
249
|
type LinkedVPEntry = {
|
|
250
250
|
id: string;
|
|
251
251
|
linkedVpId: string;
|
|
252
|
-
tenantId?: string;
|
|
253
252
|
linkedVpFrom?: Date;
|
|
253
|
+
tenantId?: string;
|
|
254
254
|
createdAt: Date;
|
|
255
255
|
};
|
|
256
256
|
type LinkedVPServiceEntry = {
|
|
@@ -430,10 +430,6 @@ declare class LinkedVPManager implements IAgentPlugin {
|
|
|
430
430
|
};
|
|
431
431
|
};
|
|
432
432
|
readonly methods: ILinkedVPManager;
|
|
433
|
-
private readonly holderDids;
|
|
434
|
-
constructor(options: {
|
|
435
|
-
holderDids: Record<string, string>;
|
|
436
|
-
});
|
|
437
433
|
private lvpPublishCredential;
|
|
438
434
|
private lvpUnpublishCredential;
|
|
439
435
|
private lvpHasEntry;
|
package/dist/index.d.ts
CHANGED
|
@@ -249,8 +249,8 @@ type GeneratePresentationArgs = {
|
|
|
249
249
|
type LinkedVPEntry = {
|
|
250
250
|
id: string;
|
|
251
251
|
linkedVpId: string;
|
|
252
|
-
tenantId?: string;
|
|
253
252
|
linkedVpFrom?: Date;
|
|
253
|
+
tenantId?: string;
|
|
254
254
|
createdAt: Date;
|
|
255
255
|
};
|
|
256
256
|
type LinkedVPServiceEntry = {
|
|
@@ -430,10 +430,6 @@ declare class LinkedVPManager implements IAgentPlugin {
|
|
|
430
430
|
};
|
|
431
431
|
};
|
|
432
432
|
readonly methods: ILinkedVPManager;
|
|
433
|
-
private readonly holderDids;
|
|
434
|
-
constructor(options: {
|
|
435
|
-
holderDids: Record<string, string>;
|
|
436
|
-
});
|
|
437
433
|
private lvpPublishCredential;
|
|
438
434
|
private lvpUnpublishCredential;
|
|
439
435
|
private lvpHasEntry;
|
package/dist/index.js
CHANGED
|
@@ -327,10 +327,6 @@ var LinkedVPManager = class {
|
|
|
327
327
|
lvpGetServiceEntries: this.lvpGetServiceEntries.bind(this),
|
|
328
328
|
lvpGeneratePresentation: this.lvpGeneratePresentation.bind(this)
|
|
329
329
|
};
|
|
330
|
-
holderDids;
|
|
331
|
-
constructor(options) {
|
|
332
|
-
this.holderDids = options.holderDids;
|
|
333
|
-
}
|
|
334
330
|
async lvpPublishCredential(args, context) {
|
|
335
331
|
const { digitalCredentialId } = args;
|
|
336
332
|
const credential = await context.agent.crsGetCredential({
|
|
@@ -403,15 +399,17 @@ var LinkedVPManager = class {
|
|
|
403
399
|
filter
|
|
404
400
|
]
|
|
405
401
|
});
|
|
406
|
-
return credentials.filter((cred) => cred.linkedVpId !== void 0 && cred.linkedVpId !== null).
|
|
407
|
-
const
|
|
408
|
-
|
|
402
|
+
return credentials.filter((cred) => cred.linkedVpId !== void 0 && cred.linkedVpId !== null).flatMap((cred) => {
|
|
403
|
+
const uniformDocument = JSON.parse(cred.uniformDocument);
|
|
404
|
+
const holderDidForEntry = this.getHolderDid(uniformDocument);
|
|
405
|
+
return holderDidForEntry && holderDidForEntry.startsWith("did:web") ? [
|
|
406
|
+
this.credentialToServiceEntry(cred, holderDidForEntry)
|
|
407
|
+
] : [];
|
|
409
408
|
});
|
|
410
409
|
}
|
|
411
410
|
async lvpGeneratePresentation(args, context) {
|
|
412
411
|
const { linkedVpId } = args;
|
|
413
412
|
const tenantId = this.parseTenantFromLinkedVpId(linkedVpId);
|
|
414
|
-
const holderDid = this.getHolderDid(tenantId);
|
|
415
413
|
const uniqueCredentials = await context.agent.crsGetUniqueCredentials({
|
|
416
414
|
filter: [
|
|
417
415
|
{
|
|
@@ -428,14 +426,29 @@ var LinkedVPManager = class {
|
|
|
428
426
|
if (uniqueCredentials.length > 1) {
|
|
429
427
|
return Promise.reject(Error(`Multiple credentials found for linkedVpId ${linkedVpId}`));
|
|
430
428
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
429
|
+
const uniqueDigitalCredential = uniqueCredentials[0];
|
|
430
|
+
if (!uniqueDigitalCredential.uniformVerifiableCredential) {
|
|
431
|
+
return Promise.reject(Error(`uniformVerifiableCredential could not be found for credential ${uniqueDigitalCredential.digitalCredential.id}`));
|
|
432
|
+
}
|
|
433
|
+
const holderDid = this.getHolderDid(uniqueDigitalCredential.uniformVerifiableCredential);
|
|
435
434
|
if (!holderDid) {
|
|
436
|
-
|
|
435
|
+
return Promise.reject(Error(`Could not extract the holder did:web from cnf nor the credentialSubject id`));
|
|
436
|
+
}
|
|
437
|
+
return createLinkedVPPresentation(holderDid, uniqueDigitalCredential, context.agent);
|
|
438
|
+
}
|
|
439
|
+
getHolderDid(uniformDocument) {
|
|
440
|
+
if ("cnf" in uniformDocument && "jwk" in uniformDocument.cnf && "kid" in uniformDocument.cnf.jwk) {
|
|
441
|
+
return uniformDocument.cnf.jwk.kid.split("#")[0];
|
|
442
|
+
}
|
|
443
|
+
if ("credentialSubject" in uniformDocument) {
|
|
444
|
+
const credentialSubject = Array.isArray(uniformDocument.credentialSubject) ? uniformDocument.credentialSubject[0] : uniformDocument.credentialSubject;
|
|
445
|
+
if ("id" in credentialSubject && credentialSubject.id) {
|
|
446
|
+
if (credentialSubject.id.startsWith("did:web")) {
|
|
447
|
+
return credentialSubject.id;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
437
450
|
}
|
|
438
|
-
return
|
|
451
|
+
return void 0;
|
|
439
452
|
}
|
|
440
453
|
parseTenantFromLinkedVpId(linkedVpId) {
|
|
441
454
|
const idx = linkedVpId.lastIndexOf("@");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../plugin.schema.json","../src/agent/LinkedVPManager.ts","../src/services/LinkedVPService.ts","../src/types/ILinkedVPManager.ts"],"sourcesContent":["{\n \"ILinkedVPManager\": {\n \"components\": {\n \"schemas\": {\n \"GeneratePresentationArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"linkedVpId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"linkedVpId\"\n ],\n \"additionalProperties\": false\n },\n \"LinkedVPPresentation\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"$ref\": \"#/components/schemas/Record<string,any>\"\n }\n ]\n },\n \"Record<string,any>\": {\n \"type\": \"object\"\n },\n \"GetServiceEntriesArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"tenantId\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"LinkedVPServiceEntry\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"const\": \"LinkedVerifiablePresentation\"\n },\n \"serviceEndpoint\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"serviceEndpoint\"\n ],\n \"additionalProperties\": false\n },\n \"HasLinkedVPEntryArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"linkedVpId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"linkedVpId\"\n ],\n \"additionalProperties\": false\n },\n \"PublishCredentialArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"digitalCredentialId\": {\n \"type\": \"string\"\n },\n \"linkedVpId\": {\n \"type\": \"string\"\n },\n \"tenantId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"digitalCredentialId\"\n ],\n \"additionalProperties\": false\n },\n \"LinkedVPEntry\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"linkedVpId\": {\n \"type\": \"string\"\n },\n \"tenantId\": {\n \"type\": \"string\"\n },\n \"linkedVpFrom\": {\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"createdAt\": {\n \"type\": \"string\",\n \"format\": \"date-time\"\n }\n },\n \"required\": [\n \"id\",\n \"linkedVpId\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"UnpublishCredentialArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"linkedVpId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"linkedVpId\"\n ],\n \"additionalProperties\": false\n }\n },\n \"methods\": {\n \"lvpGeneratePresentation\": {\n \"description\": \"Generate and return a Verifiable Presentation for a published LinkedVP This is the main endpoint handler for GET /linked-vp/\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/GeneratePresentationArgs\"\n },\n \"returnType\": {\n \"$ref\": \"#/components/schemas/LinkedVPPresentation\"\n }\n },\n \"lvpGetServiceEntries\": {\n \"description\": \"Get LinkedVP service entries for a DID to be added to a DID Document This is useful when generating DID Documents with toDidDocument\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/GetServiceEntriesArgs\"\n },\n \"returnType\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/LinkedVPServiceEntry\"\n }\n }\n },\n \"lvpHasEntry\": {\n \"description\": \"Check if a LinkedVP entry exists by linkedVpId\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/HasLinkedVPEntryArgs\"\n },\n \"returnType\": {\n \"type\": \"boolean\"\n }\n },\n \"lvpPublishCredential\": {\n \"description\": \"Publish a credential as a LinkedVP by adding it to the holder's DID Document\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/PublishCredentialArgs\"\n },\n \"returnType\": {\n \"$ref\": \"#/components/schemas/LinkedVPEntry\"\n }\n },\n \"lvpUnpublishCredential\": {\n \"description\": \"Unpublish a credential by removing its LinkedVP entry from the DID Document\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/UnpublishCredentialArgs\"\n },\n \"returnType\": {\n \"type\": \"boolean\"\n }\n }\n }\n }\n }\n}","import { DigitalCredential } from '@sphereon/ssi-sdk.data-store-types'\nimport { IAgentPlugin } from '@veramo/core'\nimport { IsNull, Not } from 'typeorm'\nimport { schema } from '../index'\nimport { createLinkedVPPresentation } from '../services/LinkedVPService'\nimport {\n GeneratePresentationArgs,\n GetServiceEntriesArgs,\n HasLinkedVPEntryArgs,\n ILinkedVPManager,\n LinkedVPEntry,\n LinkedVPPresentation,\n LinkedVPServiceEntry,\n PublishCredentialArgs,\n RequiredContext,\n UnpublishCredentialArgs,\n} from '../types'\n\n// Exposing the methods here for any REST implementation\nexport const linkedVPManagerMethods: Array<string> = [\n 'lvpPublishCredential',\n 'lvpUnpublishCredential',\n 'lvpHasEntry',\n 'lvpGetServiceEntries',\n 'lvpGeneratePresentation',\n]\n\n/**\n * {@inheritDoc ILinkedVPManager}\n */\nexport class LinkedVPManager implements IAgentPlugin {\n readonly schema = schema.ILinkedVPManager\n readonly methods: ILinkedVPManager = {\n lvpPublishCredential: this.lvpPublishCredential.bind(this),\n lvpUnpublishCredential: this.lvpUnpublishCredential.bind(this),\n lvpHasEntry: this.lvpHasEntry.bind(this),\n lvpGetServiceEntries: this.lvpGetServiceEntries.bind(this),\n lvpGeneratePresentation: this.lvpGeneratePresentation.bind(this),\n }\n\n private readonly holderDids: Record<string, string>\n\n constructor(options: { holderDids: Record<string, string> }) {\n this.holderDids = options.holderDids\n }\n\n private async lvpPublishCredential(args: PublishCredentialArgs, context: RequiredContext): Promise<LinkedVPEntry> {\n const { digitalCredentialId } = args\n\n const credential: DigitalCredential = await context.agent.crsGetCredential({ id: digitalCredentialId })\n\n if (credential.linkedVpId) {\n return Promise.reject(new Error(`Credential ${digitalCredentialId} is already published with linkedVpId ${credential.linkedVpId}`))\n }\n\n const linkedVpId = this.buildLinkedVpId(args.linkedVpId, credential.tenantId)\n\n await this.ensureLinkedVpIdUnique(linkedVpId, context, credential.tenantId)\n\n const publishedAt = new Date()\n await context.agent.crsUpdateCredential({\n id: digitalCredentialId,\n linkedVpId,\n linkedVpFrom: publishedAt,\n })\n\n return {\n id: credential.id,\n linkedVpId,\n tenantId: credential.tenantId,\n linkedVpFrom: publishedAt,\n createdAt: credential.createdAt,\n }\n }\n\n private async lvpUnpublishCredential(args: UnpublishCredentialArgs, context: RequiredContext): Promise<boolean> {\n const { linkedVpId } = args\n\n // Find credential by linkedVpId and tenantId\n const credentials = await context.agent.crsGetCredentials({\n filter: [{ linkedVpId }],\n })\n if (credentials.length === 0) {\n return Promise.reject(Error(`No credential found with linkedVpId ${linkedVpId}`))\n }\n\n const credential = credentials[0]\n await context.agent.crsUpdateCredential({\n id: credential.id,\n linkedVpId: undefined,\n linkedVpFrom: undefined,\n })\n\n return true\n }\n\n private async lvpHasEntry(args: HasLinkedVPEntryArgs, context: RequiredContext): Promise<boolean> {\n const { linkedVpId } = args\n\n try {\n const credentials = await context.agent.crsGetCredentials({\n filter: [{ linkedVpId }],\n })\n return credentials.length > 0\n } catch (error) {\n return false\n }\n }\n\n private async lvpGetServiceEntries(args: GetServiceEntriesArgs, context: RequiredContext): Promise<Array<LinkedVPServiceEntry>> {\n const { tenantId } = args\n\n // Get all published credentials (credentials with linkedVpId set)\n const filter: any = { linkedVpId: Not(IsNull()) }\n if (tenantId) {\n filter.tenantId = tenantId\n }\n\n const credentials = await context.agent.crsGetCredentials({\n filter: [filter],\n })\n\n return credentials\n .filter((cred) => cred.linkedVpId !== undefined && cred.linkedVpId !== null)\n .map((cred) => {\n const holderDidForEntry = this.getHolderDid(cred.tenantId)\n return this.credentialToServiceEntry(cred, holderDidForEntry)\n })\n }\n\n private async lvpGeneratePresentation(args: GeneratePresentationArgs, context: RequiredContext): Promise<LinkedVPPresentation> {\n const { linkedVpId } = args\n const tenantId = this.parseTenantFromLinkedVpId(linkedVpId)\n const holderDid = this.getHolderDid(tenantId)\n\n const uniqueCredentials = await context.agent.crsGetUniqueCredentials({\n filter: [\n {\n linkedVpId: args.linkedVpId,\n ...(tenantId && { tenantId }),\n },\n ],\n })\n if (uniqueCredentials.length === 0) {\n return Promise.reject(Error(`No published credentials found for linkedVpId ${linkedVpId}`))\n }\n if (uniqueCredentials.length > 1) {\n return Promise.reject(Error(`Multiple credentials found for linkedVpId ${linkedVpId}`))\n }\n\n // Generate the Verifiable Presentation with all published credentials\n return createLinkedVPPresentation(holderDid, uniqueCredentials[0], context.agent)\n }\n\n private getHolderDid(tenantId: string | undefined) {\n const holderDid = this.holderDids[tenantId ?? 'default']\n if (!holderDid) {\n throw Error(`No holder did supplied for tenant ${tenantId ?? 'default'}`)\n }\n return holderDid\n }\n\n private parseTenantFromLinkedVpId(linkedVpId: string): string | undefined {\n const idx = linkedVpId.lastIndexOf('@')\n return idx === -1 ? undefined : linkedVpId.substring(idx + 1)\n }\n\n private generateLinkedVpId(): string {\n return `lvp-${Math.random().toString(36).substring(2, 15)}`\n }\n\n private async ensureLinkedVpIdUnique(linkedVpId: string, context: RequiredContext, tenantId?: string): Promise<void> {\n const credentials = await context.agent.crsGetCredentials({\n filter: [{ linkedVpId, ...(tenantId && { tenantId }) }],\n })\n\n if (credentials.length > 0) {\n throw new Error(`LinkedVP ID ${linkedVpId} already exists${tenantId ? ` for tenant ${tenantId}` : ''}`)\n }\n }\n\n private buildLinkedVpId(linkedVpId: string | undefined, tenantId: string | undefined) {\n let finalLinkedVpId = linkedVpId || this.generateLinkedVpId()\n\n // Append tenantId if provided and not already present\n if (tenantId && tenantId !== '' && !finalLinkedVpId.includes('@')) {\n finalLinkedVpId = `${finalLinkedVpId}@${tenantId}`\n }\n return finalLinkedVpId\n }\n\n private getBaseUrlFromDid(holderDid: string): string {\n if (!holderDid.startsWith('did:web:')) {\n throw new Error(`Invalid DID: ${holderDid}, must be did:web`)\n }\n\n const withoutPrefix = holderDid.replace('did:web:', '') // example.com:tenants:tenant1\n const parts = withoutPrefix.split(':')\n const domain = parts.shift()! // example.com\n const path = parts.join('/') // tenants/tenant1\n\n return path\n ? `https://${domain}/${path}` // https://example.com/tenants/tenant1\n : `https://${domain}` // https://example.com\n }\n\n private buildServiceEndpoint(holderDid: string, linkedVpId: string): string {\n const baseUrl = this.getBaseUrlFromDid(holderDid)\n const cleanBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n return `${cleanBaseUrl}/linked-vp/${linkedVpId}`\n }\n\n private credentialToServiceEntry(credential: DigitalCredential, holderDid: string): LinkedVPServiceEntry {\n if (!credential.linkedVpId) {\n throw new Error(`Credential ${credential.id} does not have a linkedVpId`)\n }\n\n return {\n id: `${holderDid}#${credential.linkedVpId}`,\n type: 'LinkedVerifiablePresentation',\n serviceEndpoint: this.buildServiceEndpoint(holderDid, credential.linkedVpId),\n }\n }\n}\n","import { UniqueDigitalCredential } from '@sphereon/ssi-sdk.credential-store'\nimport { calculateSdHash, defaultGenerateDigest, PartialSdJwtKbJwt } from '@sphereon/ssi-sdk.sd-jwt'\n\nimport {\n CredentialMapper,\n DocumentFormat,\n Loggers,\n OriginalVerifiableCredential,\n SdJwtDecodedVerifiableCredential,\n WrappedVerifiableCredential,\n} from '@sphereon/ssi-types'\nimport { LinkedVPPresentation, LOGGER_NAMESPACE, RequiredContext } from '../types'\n\nconst logger = Loggers.DEFAULT.get(LOGGER_NAMESPACE)\nconst CLOCK_SKEW = 120 // TODO make adjustable?\n\n/**\n * Extracts the original credential from various wrapper types\n */\nfunction extractOriginalCredential(\n credential: UniqueDigitalCredential | WrappedVerifiableCredential | OriginalVerifiableCredential,\n): OriginalVerifiableCredential {\n if (typeof credential === 'string') {\n return credential\n }\n\n if ('digitalCredential' in credential) {\n const udc = credential as UniqueDigitalCredential\n if (udc.originalVerifiableCredential) {\n return udc.originalVerifiableCredential\n }\n return udc.uniformVerifiableCredential as OriginalVerifiableCredential\n }\n\n if ('original' in credential) {\n return credential.original\n }\n\n return credential as OriginalVerifiableCredential\n}\n\n/**\n * Creates a Verifiable Presentation for LinkedVP publishing\n * Contains multiple credentials in a single JWT VP\n * No nonce or audience since this is for publishing, not responding to verification\n */\nexport async function createLinkedVPPresentation(\n holderDid: string,\n credential: UniqueDigitalCredential,\n agent: RequiredContext['agent'],\n): Promise<LinkedVPPresentation> {\n logger.debug(`Creating LinkedVP presentation for ${holderDid} of credential ${credential.id}`)\n\n const identifier = await agent.identifierManagedGet({ identifier: holderDid })\n const originalCredential = extractOriginalCredential(credential)\n const documentFormat = CredentialMapper.detectDocumentType(originalCredential)\n switch (documentFormat) {\n case DocumentFormat.SD_JWT_VC: {\n // SD-JWT with KB-JWT\n const decodedSdJwt = await CredentialMapper.decodeSdJwtVcAsync(\n typeof originalCredential === 'string' ? originalCredential : (originalCredential as SdJwtDecodedVerifiableCredential).compactSdJwtVc,\n defaultGenerateDigest,\n )\n\n const hashAlg = decodedSdJwt.signedPayload._sd_alg ?? 'sha-256'\n const sdHash = calculateSdHash(decodedSdJwt.compactSdJwtVc, hashAlg, defaultGenerateDigest)\n const kbJwtPayload: PartialSdJwtKbJwt['payload'] = {\n iat: Math.floor(Date.now() / 1000 - CLOCK_SKEW),\n sd_hash: sdHash,\n }\n\n const presentationResult = await agent.createSdJwtPresentation({\n presentation: decodedSdJwt.compactSdJwtVc,\n kb: {\n payload: kbJwtPayload as any, // FIXME?\n },\n })\n\n return {\n documentFormat,\n presentationPayload: presentationResult.presentation,\n }\n }\n case DocumentFormat.JSONLD: {\n // JSON-LD VC - create JSON-LD VP with challenge and domain in proof\n const vcObject = typeof originalCredential === 'string' ? JSON.parse(originalCredential) : originalCredential\n\n const vpObject = {\n '@context': ['https://www.w3.org/2018/credentials/v1'],\n type: ['VerifiablePresentation'],\n verifiableCredential: [vcObject],\n holder: holderDid,\n }\n\n // Create JSON-LD VP with proof\n const verifiablePresentationSP = await agent.createVerifiablePresentation({\n presentation: vpObject,\n proofFormat: 'lds',\n keyRef: identifier.kmsKeyRef || identifier.kid,\n })\n return {\n documentFormat,\n presentationPayload: verifiablePresentationSP,\n }\n }\n case DocumentFormat.MSO_MDOC: {\n // ISO mdoc - create mdoc VP token\n // This is a placeholder implementation\n // Full implementation would require:\n // 1. Decode the mdoc using CredentialMapper or mdoc utilities\n // 2. Build proper mdoc VP token with session transcript\n // 3. Include nonce/audience in the session transcript\n logger.warning('mso_mdoc format has basic support - production use requires proper mdoc VP token implementation')\n\n return {\n documentFormat,\n presentationPayload: originalCredential,\n }\n }\n default: {\n // JWT VC - create JWT VP with nonce and aud in payload\n const vcJwt = typeof originalCredential === 'string' ? originalCredential : JSON.stringify(originalCredential)\n\n // Create VP JWT using agent method\n const vpPayload = {\n iss: holderDid,\n vp: {\n '@context': ['https://www.w3.org/2018/credentials/v1'],\n type: ['VerifiablePresentation'],\n holder: holderDid,\n verifiableCredential: [vcJwt],\n },\n iat: Math.floor(Date.now() / 1000 - CLOCK_SKEW),\n exp: Math.floor(Date.now() / 1000 + 600 + CLOCK_SKEW), // 10 minutes\n }\n\n // Use the agent's JWT creation capability\n const vpJwt = await agent.createVerifiablePresentation({\n presentation: vpPayload.vp,\n proofFormat: 'jwt',\n keyRef: identifier.kmsKeyRef || identifier.kid,\n })\n\n return {\n documentFormat,\n presentationPayload: (vpJwt.proof && 'jwt' in vpJwt.proof && vpJwt.proof.jwt) || vpJwt,\n }\n }\n }\n}\n","import { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'\nimport { ICredentialStore } from '@sphereon/ssi-sdk.credential-store'\nimport { VcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'\nimport { ISDJwtPlugin } from '@sphereon/ssi-sdk.sd-jwt'\nimport { DocumentFormat } from '@sphereon/ssi-types'\nimport { IAgentContext, IPluginMethodMap } from '@veramo/core'\nimport { IKeyManager } from '@veramo/core/src/types/IKeyManager'\n\nexport const LOGGER_NAMESPACE = 'sphereon:linked-vp'\n\nexport type LinkedVPPresentation = {\n documentFormat: DocumentFormat\n presentationPayload: string | Record<string, any>\n}\n\nexport interface ILinkedVPManager extends IPluginMethodMap {\n /**\n * Publish a credential as a LinkedVP by adding it to the holder's DID Document\n * @param args - Publication arguments including credential ID and scope configuration\n * @param context - Agent context\n */\n lvpPublishCredential(args: PublishCredentialArgs, context: RequiredContext): Promise<LinkedVPEntry>\n\n /**\n * Unpublish a credential by removing its LinkedVP entry from the DID Document\n * @param args - Unpublish arguments\n * @param context - Agent context\n */\n lvpUnpublishCredential(args: UnpublishCredentialArgs, context: RequiredContext): Promise<boolean>\n\n /**\n * Check if a LinkedVP entry exists by linkedVpId\n * @param args - Query arguments\n * @param context - Agent context\n */\n lvpHasEntry(args: HasLinkedVPEntryArgs, context: RequiredContext): Promise<boolean>\n\n /**\n * Get LinkedVP service entries for a DID to be added to a DID Document\n * This is useful when generating DID Documents with toDidDocument\n * @param args - Query arguments for the DID\n * @param context - Agent context\n */\n lvpGetServiceEntries(args: GetServiceEntriesArgs, context: RequiredContext): Promise<Array<LinkedVPServiceEntry>>\n\n /**\n * Generate and return a Verifiable Presentation for a published LinkedVP\n * This is the main endpoint handler for GET /linked-vp/{linkedVpId}\n * @param args - Generation arguments\n * @param context - Agent context\n */\n lvpGeneratePresentation(args: GeneratePresentationArgs, context: RequiredContext): Promise<LinkedVPPresentation>\n}\n\nexport type PublishCredentialArgs = {\n digitalCredentialId: string\n linkedVpId?: string // Optional: if not provided, will be auto-generated\n}\n\nexport type UnpublishCredentialArgs = {\n linkedVpId: string\n}\n\nexport type HasLinkedVPEntryArgs = {\n linkedVpId: string\n}\n\nexport type GetServiceEntriesArgs = {\n tenantId?: string\n}\n\nexport type GeneratePresentationArgs = {\n linkedVpId: string\n}\n\nexport type LinkedVPEntry = {\n id: string\n linkedVpId: string\n tenantId?: string\n linkedVpFrom?: Date\n createdAt: Date\n}\n\nexport type LinkedVPServiceEntry = {\n id: string\n type: 'LinkedVerifiablePresentation'\n serviceEndpoint: string\n}\n\nexport type RequiredContext = IAgentContext<IIdentifierResolution & ICredentialStore & IKeyManager & VcdmCredentialPlugin & ISDJwtPlugin>\n"],"mappings":"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","names":["IsNull","Not","calculateSdHash","defaultGenerateDigest","CredentialMapper","DocumentFormat","Loggers","LOGGER_NAMESPACE","logger","Loggers","DEFAULT","get","LOGGER_NAMESPACE","CLOCK_SKEW","extractOriginalCredential","credential","udc","originalVerifiableCredential","uniformVerifiableCredential","original","createLinkedVPPresentation","holderDid","agent","debug","id","identifier","identifierManagedGet","originalCredential","documentFormat","CredentialMapper","detectDocumentType","DocumentFormat","SD_JWT_VC","decodedSdJwt","decodeSdJwtVcAsync","compactSdJwtVc","defaultGenerateDigest","hashAlg","signedPayload","_sd_alg","sdHash","calculateSdHash","kbJwtPayload","iat","Math","floor","Date","now","sd_hash","presentationResult","createSdJwtPresentation","presentation","kb","payload","presentationPayload","JSONLD","vcObject","JSON","parse","vpObject","type","verifiableCredential","holder","verifiablePresentationSP","createVerifiablePresentation","proofFormat","keyRef","kmsKeyRef","kid","MSO_MDOC","warning","vcJwt","stringify","vpPayload","iss","vp","exp","vpJwt","proof","jwt","linkedVPManagerMethods","LinkedVPManager","schema","ILinkedVPManager","methods","lvpPublishCredential","bind","lvpUnpublishCredential","lvpHasEntry","lvpGetServiceEntries","lvpGeneratePresentation","holderDids","options","args","context","digitalCredentialId","credential","agent","crsGetCredential","id","linkedVpId","Promise","reject","Error","buildLinkedVpId","tenantId","ensureLinkedVpIdUnique","publishedAt","Date","crsUpdateCredential","linkedVpFrom","createdAt","credentials","crsGetCredentials","filter","length","undefined","error","Not","IsNull","cred","map","holderDidForEntry","getHolderDid","credentialToServiceEntry","parseTenantFromLinkedVpId","holderDid","uniqueCredentials","crsGetUniqueCredentials","createLinkedVPPresentation","idx","lastIndexOf","substring","generateLinkedVpId","Math","random","toString","finalLinkedVpId","includes","getBaseUrlFromDid","startsWith","withoutPrefix","replace","parts","split","domain","shift","path","join","buildServiceEndpoint","baseUrl","cleanBaseUrl","endsWith","slice","type","serviceEndpoint"]}
|
|
1
|
+
{"version":3,"sources":["../plugin.schema.json","../src/agent/LinkedVPManager.ts","../src/services/LinkedVPService.ts","../src/types/ILinkedVPManager.ts"],"sourcesContent":["{\n \"ILinkedVPManager\": {\n \"components\": {\n \"schemas\": {\n \"GeneratePresentationArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"linkedVpId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"linkedVpId\"\n ],\n \"additionalProperties\": false\n },\n \"LinkedVPPresentation\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"$ref\": \"#/components/schemas/Record<string,any>\"\n }\n ]\n },\n \"Record<string,any>\": {\n \"type\": \"object\"\n },\n \"GetServiceEntriesArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"tenantId\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"LinkedVPServiceEntry\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"const\": \"LinkedVerifiablePresentation\"\n },\n \"serviceEndpoint\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"serviceEndpoint\"\n ],\n \"additionalProperties\": false\n },\n \"HasLinkedVPEntryArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"linkedVpId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"linkedVpId\"\n ],\n \"additionalProperties\": false\n },\n \"PublishCredentialArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"digitalCredentialId\": {\n \"type\": \"string\"\n },\n \"linkedVpId\": {\n \"type\": \"string\"\n },\n \"tenantId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"digitalCredentialId\"\n ],\n \"additionalProperties\": false\n },\n \"LinkedVPEntry\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"linkedVpId\": {\n \"type\": \"string\"\n },\n \"tenantId\": {\n \"type\": \"string\"\n },\n \"linkedVpFrom\": {\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"createdAt\": {\n \"type\": \"string\",\n \"format\": \"date-time\"\n }\n },\n \"required\": [\n \"id\",\n \"linkedVpId\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"UnpublishCredentialArgs\": {\n \"type\": \"object\",\n \"properties\": {\n \"linkedVpId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"linkedVpId\"\n ],\n \"additionalProperties\": false\n }\n },\n \"methods\": {\n \"lvpGeneratePresentation\": {\n \"description\": \"Generate and return a Verifiable Presentation for a published LinkedVP This is the main endpoint handler for GET /linked-vp/\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/GeneratePresentationArgs\"\n },\n \"returnType\": {\n \"$ref\": \"#/components/schemas/LinkedVPPresentation\"\n }\n },\n \"lvpGetServiceEntries\": {\n \"description\": \"Get LinkedVP service entries for a DID to be added to a DID Document This is useful when generating DID Documents with toDidDocument\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/GetServiceEntriesArgs\"\n },\n \"returnType\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/LinkedVPServiceEntry\"\n }\n }\n },\n \"lvpHasEntry\": {\n \"description\": \"Check if a LinkedVP entry exists by linkedVpId\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/HasLinkedVPEntryArgs\"\n },\n \"returnType\": {\n \"type\": \"boolean\"\n }\n },\n \"lvpPublishCredential\": {\n \"description\": \"Publish a credential as a LinkedVP by adding it to the holder's DID Document\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/PublishCredentialArgs\"\n },\n \"returnType\": {\n \"$ref\": \"#/components/schemas/LinkedVPEntry\"\n }\n },\n \"lvpUnpublishCredential\": {\n \"description\": \"Unpublish a credential by removing its LinkedVP entry from the DID Document\",\n \"arguments\": {\n \"$ref\": \"#/components/schemas/UnpublishCredentialArgs\"\n },\n \"returnType\": {\n \"type\": \"boolean\"\n }\n }\n }\n }\n }\n}","import { DigitalCredential } from '@sphereon/ssi-sdk.data-store-types'\nimport { type IVerifiableCredential } from '@sphereon/ssi-types'\nimport { IAgentPlugin } from '@veramo/core'\nimport { IsNull, Not } from 'typeorm'\nimport { schema } from '../index'\nimport { createLinkedVPPresentation } from '../services/LinkedVPService'\nimport {\n GeneratePresentationArgs,\n GetServiceEntriesArgs,\n HasLinkedVPEntryArgs,\n ILinkedVPManager,\n LinkedVPEntry,\n LinkedVPPresentation,\n LinkedVPServiceEntry,\n PublishCredentialArgs,\n RequiredContext,\n UnpublishCredentialArgs,\n} from '../types'\n\n// Exposing the methods here for any REST implementation\nexport const linkedVPManagerMethods: Array<string> = [\n 'lvpPublishCredential',\n 'lvpUnpublishCredential',\n 'lvpHasEntry',\n 'lvpGetServiceEntries',\n 'lvpGeneratePresentation',\n]\n\n/**\n * {@inheritDoc ILinkedVPManager}\n */\nexport class LinkedVPManager implements IAgentPlugin {\n readonly schema = schema.ILinkedVPManager\n readonly methods: ILinkedVPManager = {\n lvpPublishCredential: this.lvpPublishCredential.bind(this),\n lvpUnpublishCredential: this.lvpUnpublishCredential.bind(this),\n lvpHasEntry: this.lvpHasEntry.bind(this),\n lvpGetServiceEntries: this.lvpGetServiceEntries.bind(this),\n lvpGeneratePresentation: this.lvpGeneratePresentation.bind(this),\n }\n\n private async lvpPublishCredential(args: PublishCredentialArgs, context: RequiredContext): Promise<LinkedVPEntry> {\n const { digitalCredentialId } = args\n\n const credential: DigitalCredential = await context.agent.crsGetCredential({ id: digitalCredentialId })\n\n if (credential.linkedVpId) {\n return Promise.reject(new Error(`Credential ${digitalCredentialId} is already published with linkedVpId ${credential.linkedVpId}`))\n }\n\n const linkedVpId = this.buildLinkedVpId(args.linkedVpId, credential.tenantId)\n\n await this.ensureLinkedVpIdUnique(linkedVpId, context, credential.tenantId)\n\n const publishedAt = new Date()\n await context.agent.crsUpdateCredential({\n id: digitalCredentialId,\n linkedVpId,\n linkedVpFrom: publishedAt,\n })\n\n return {\n id: credential.id,\n linkedVpId,\n tenantId: credential.tenantId,\n linkedVpFrom: publishedAt,\n createdAt: credential.createdAt,\n }\n }\n\n private async lvpUnpublishCredential(args: UnpublishCredentialArgs, context: RequiredContext): Promise<boolean> {\n const { linkedVpId } = args\n\n // Find credential by linkedVpId and tenantId\n const credentials = await context.agent.crsGetCredentials({\n filter: [{ linkedVpId }],\n })\n if (credentials.length === 0) {\n return Promise.reject(Error(`No credential found with linkedVpId ${linkedVpId}`))\n }\n\n const credential = credentials[0]\n await context.agent.crsUpdateCredential({\n id: credential.id,\n linkedVpId: undefined,\n linkedVpFrom: undefined,\n })\n\n return true\n }\n\n private async lvpHasEntry(args: HasLinkedVPEntryArgs, context: RequiredContext): Promise<boolean> {\n const { linkedVpId } = args\n\n try {\n const credentials = await context.agent.crsGetCredentials({\n filter: [{ linkedVpId }],\n })\n return credentials.length > 0\n } catch (error) {\n return false\n }\n }\n\n private async lvpGetServiceEntries(args: GetServiceEntriesArgs, context: RequiredContext): Promise<Array<LinkedVPServiceEntry>> {\n const { tenantId } = args\n\n // Get all published credentials (credentials with linkedVpId set)\n const filter: any = { linkedVpId: Not(IsNull()) }\n if (tenantId) {\n filter.tenantId = tenantId\n }\n\n const credentials = await context.agent.crsGetCredentials({\n filter: [filter],\n })\n\n return credentials\n .filter((cred) => cred.linkedVpId !== undefined && cred.linkedVpId !== null)\n .flatMap((cred) => {\n const uniformDocument = JSON.parse(cred.uniformDocument) as IVerifiableCredential\n const holderDidForEntry = this.getHolderDid(uniformDocument)\n return holderDidForEntry && holderDidForEntry.startsWith('did:web') ? [this.credentialToServiceEntry(cred, holderDidForEntry)] : []\n })\n }\n\n private async lvpGeneratePresentation(args: GeneratePresentationArgs, context: RequiredContext): Promise<LinkedVPPresentation> {\n const { linkedVpId } = args\n const tenantId = this.parseTenantFromLinkedVpId(linkedVpId)\n\n const uniqueCredentials = await context.agent.crsGetUniqueCredentials({\n filter: [\n {\n linkedVpId: args.linkedVpId,\n ...(tenantId && { tenantId }),\n },\n ],\n })\n if (uniqueCredentials.length === 0) {\n return Promise.reject(Error(`No published credentials found for linkedVpId ${linkedVpId}`))\n }\n if (uniqueCredentials.length > 1) {\n return Promise.reject(Error(`Multiple credentials found for linkedVpId ${linkedVpId}`))\n }\n\n const uniqueDigitalCredential = uniqueCredentials[0]\n if (!uniqueDigitalCredential.uniformVerifiableCredential) {\n return Promise.reject(Error(`uniformVerifiableCredential could not be found for credential ${uniqueDigitalCredential.digitalCredential.id}`))\n }\n const holderDid = this.getHolderDid(uniqueDigitalCredential.uniformVerifiableCredential)\n if (!holderDid) {\n return Promise.reject(Error(`Could not extract the holder did:web from cnf nor the credentialSubject id`))\n }\n\n // Generate the Verifiable Presentation with all published credentials\n return createLinkedVPPresentation(holderDid, uniqueDigitalCredential, context.agent)\n }\n\n private getHolderDid(uniformDocument: IVerifiableCredential): string | undefined {\n // Determine holder DID for identifier resolution\n if ('cnf' in uniformDocument && 'jwk' in uniformDocument.cnf && 'kid' in uniformDocument.cnf.jwk) {\n return uniformDocument.cnf.jwk.kid.split('#')[0]\n }\n\n if ('credentialSubject' in uniformDocument) {\n const credentialSubject = Array.isArray(uniformDocument.credentialSubject)\n ? uniformDocument.credentialSubject[0]\n : uniformDocument.credentialSubject\n if ('id' in credentialSubject && credentialSubject.id) {\n if (credentialSubject.id.startsWith('did:web')) {\n return credentialSubject.id\n }\n }\n }\n\n return undefined\n }\n\n private parseTenantFromLinkedVpId(linkedVpId: string): string | undefined {\n const idx = linkedVpId.lastIndexOf('@')\n return idx === -1 ? undefined : linkedVpId.substring(idx + 1)\n }\n\n private generateLinkedVpId(): string {\n return `lvp-${Math.random().toString(36).substring(2, 15)}`\n }\n\n private async ensureLinkedVpIdUnique(linkedVpId: string, context: RequiredContext, tenantId?: string): Promise<void> {\n const credentials = await context.agent.crsGetCredentials({\n filter: [{ linkedVpId, ...(tenantId && { tenantId }) }],\n })\n\n if (credentials.length > 0) {\n throw new Error(`LinkedVP ID ${linkedVpId} already exists${tenantId ? ` for tenant ${tenantId}` : ''}`)\n }\n }\n\n private buildLinkedVpId(linkedVpId: string | undefined, tenantId: string | undefined) {\n let finalLinkedVpId = linkedVpId || this.generateLinkedVpId()\n\n // Append tenantId if provided and not already present\n if (tenantId && tenantId !== '' && !finalLinkedVpId.includes('@')) {\n finalLinkedVpId = `${finalLinkedVpId}@${tenantId}`\n }\n return finalLinkedVpId\n }\n\n private getBaseUrlFromDid(holderDid: string): string {\n if (!holderDid.startsWith('did:web:')) {\n throw new Error(`Invalid DID: ${holderDid}, must be did:web`)\n }\n\n const withoutPrefix = holderDid.replace('did:web:', '') // example.com:tenants:tenant1\n const parts = withoutPrefix.split(':')\n const domain = parts.shift()! // example.com\n const path = parts.join('/') // tenants/tenant1\n\n return path\n ? `https://${domain}/${path}` // https://example.com/tenants/tenant1\n : `https://${domain}` // https://example.com\n }\n\n private buildServiceEndpoint(holderDid: string, linkedVpId: string): string {\n const baseUrl = this.getBaseUrlFromDid(holderDid)\n const cleanBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n return `${cleanBaseUrl}/linked-vp/${linkedVpId}`\n }\n\n private credentialToServiceEntry(credential: DigitalCredential, holderDid: string): LinkedVPServiceEntry {\n if (!credential.linkedVpId) {\n throw new Error(`Credential ${credential.id} does not have a linkedVpId`)\n }\n\n return {\n id: `${holderDid}#${credential.linkedVpId}`,\n type: 'LinkedVerifiablePresentation',\n serviceEndpoint: this.buildServiceEndpoint(holderDid, credential.linkedVpId),\n }\n }\n}\n","import { UniqueDigitalCredential } from '@sphereon/ssi-sdk.credential-store'\nimport { calculateSdHash, defaultGenerateDigest, PartialSdJwtKbJwt } from '@sphereon/ssi-sdk.sd-jwt'\n\nimport {\n CredentialMapper,\n DocumentFormat,\n Loggers,\n OriginalVerifiableCredential,\n SdJwtDecodedVerifiableCredential,\n WrappedVerifiableCredential,\n} from '@sphereon/ssi-types'\nimport { LinkedVPPresentation, LOGGER_NAMESPACE, RequiredContext } from '../types'\n\nconst logger = Loggers.DEFAULT.get(LOGGER_NAMESPACE)\nconst CLOCK_SKEW = 120 // TODO make adjustable?\n\n/**\n * Extracts the original credential from various wrapper types\n */\nfunction extractOriginalCredential(\n credential: UniqueDigitalCredential | WrappedVerifiableCredential | OriginalVerifiableCredential,\n): OriginalVerifiableCredential {\n if (typeof credential === 'string') {\n return credential\n }\n\n if ('digitalCredential' in credential) {\n const udc = credential as UniqueDigitalCredential\n if (udc.originalVerifiableCredential) {\n return udc.originalVerifiableCredential\n }\n return udc.uniformVerifiableCredential as OriginalVerifiableCredential\n }\n\n if ('original' in credential) {\n return credential.original\n }\n\n return credential as OriginalVerifiableCredential\n}\n\n/**\n * Creates a Verifiable Presentation for LinkedVP publishing\n * Contains multiple credentials in a single JWT VP\n * No nonce or audience since this is for publishing, not responding to verification\n */\nexport async function createLinkedVPPresentation(\n holderDid: string,\n credential: UniqueDigitalCredential,\n agent: RequiredContext['agent'],\n): Promise<LinkedVPPresentation> {\n logger.debug(`Creating LinkedVP presentation for ${holderDid} of credential ${credential.id}`)\n\n const identifier = await agent.identifierManagedGet({ identifier: holderDid })\n const originalCredential = extractOriginalCredential(credential)\n const documentFormat = CredentialMapper.detectDocumentType(originalCredential)\n switch (documentFormat) {\n case DocumentFormat.SD_JWT_VC: {\n // SD-JWT with KB-JWT\n const decodedSdJwt = await CredentialMapper.decodeSdJwtVcAsync(\n typeof originalCredential === 'string' ? originalCredential : (originalCredential as SdJwtDecodedVerifiableCredential).compactSdJwtVc,\n defaultGenerateDigest,\n )\n\n const hashAlg = decodedSdJwt.signedPayload._sd_alg ?? 'sha-256'\n const sdHash = calculateSdHash(decodedSdJwt.compactSdJwtVc, hashAlg, defaultGenerateDigest)\n const kbJwtPayload: PartialSdJwtKbJwt['payload'] = {\n iat: Math.floor(Date.now() / 1000 - CLOCK_SKEW),\n sd_hash: sdHash,\n }\n\n const presentationResult = await agent.createSdJwtPresentation({\n presentation: decodedSdJwt.compactSdJwtVc,\n kb: {\n payload: kbJwtPayload as any, // FIXME?\n },\n })\n\n return {\n documentFormat,\n presentationPayload: presentationResult.presentation,\n }\n }\n case DocumentFormat.JSONLD: {\n // JSON-LD VC - create JSON-LD VP with challenge and domain in proof\n const vcObject = typeof originalCredential === 'string' ? JSON.parse(originalCredential) : originalCredential\n\n const vpObject = {\n '@context': ['https://www.w3.org/2018/credentials/v1'],\n type: ['VerifiablePresentation'],\n verifiableCredential: [vcObject],\n holder: holderDid,\n }\n\n // Create JSON-LD VP with proof\n const verifiablePresentationSP = await agent.createVerifiablePresentation({\n presentation: vpObject,\n proofFormat: 'lds',\n keyRef: identifier.kmsKeyRef || identifier.kid,\n })\n return {\n documentFormat,\n presentationPayload: verifiablePresentationSP,\n }\n }\n case DocumentFormat.MSO_MDOC: {\n // ISO mdoc - create mdoc VP token\n // This is a placeholder implementation\n // Full implementation would require:\n // 1. Decode the mdoc using CredentialMapper or mdoc utilities\n // 2. Build proper mdoc VP token with session transcript\n // 3. Include nonce/audience in the session transcript\n logger.warning('mso_mdoc format has basic support - production use requires proper mdoc VP token implementation')\n\n return {\n documentFormat,\n presentationPayload: originalCredential,\n }\n }\n default: {\n // JWT VC - create JWT VP with nonce and aud in payload\n const vcJwt = typeof originalCredential === 'string' ? originalCredential : JSON.stringify(originalCredential)\n\n // Create VP JWT using agent method\n const vpPayload = {\n iss: holderDid,\n vp: {\n '@context': ['https://www.w3.org/2018/credentials/v1'],\n type: ['VerifiablePresentation'],\n holder: holderDid,\n verifiableCredential: [vcJwt],\n },\n iat: Math.floor(Date.now() / 1000 - CLOCK_SKEW),\n exp: Math.floor(Date.now() / 1000 + 600 + CLOCK_SKEW), // 10 minutes\n }\n\n // Use the agent's JWT creation capability\n const vpJwt = await agent.createVerifiablePresentation({\n presentation: vpPayload.vp,\n proofFormat: 'jwt',\n keyRef: identifier.kmsKeyRef || identifier.kid,\n })\n\n return {\n documentFormat,\n presentationPayload: (vpJwt.proof && 'jwt' in vpJwt.proof && vpJwt.proof.jwt) || vpJwt,\n }\n }\n }\n}\n","import { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'\nimport { ICredentialStore } from '@sphereon/ssi-sdk.credential-store'\nimport { VcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'\nimport { ISDJwtPlugin } from '@sphereon/ssi-sdk.sd-jwt'\nimport { DocumentFormat } from '@sphereon/ssi-types'\nimport { IAgentContext, IPluginMethodMap } from '@veramo/core'\nimport { IKeyManager } from '@veramo/core/src/types/IKeyManager'\n\nexport const LOGGER_NAMESPACE = 'sphereon:linked-vp'\n\nexport type LinkedVPPresentation = {\n documentFormat: DocumentFormat\n presentationPayload: string | Record<string, any>\n}\n\nexport interface ILinkedVPManager extends IPluginMethodMap {\n /**\n * Publish a credential as a LinkedVP by adding it to the holder's DID Document\n * @param args - Publication arguments including credential ID and scope configuration\n * @param context - Agent context\n */\n lvpPublishCredential(args: PublishCredentialArgs, context: RequiredContext): Promise<LinkedVPEntry>\n\n /**\n * Unpublish a credential by removing its LinkedVP entry from the DID Document\n * @param args - Unpublish arguments\n * @param context - Agent context\n */\n lvpUnpublishCredential(args: UnpublishCredentialArgs, context: RequiredContext): Promise<boolean>\n\n /**\n * Check if a LinkedVP entry exists by linkedVpId\n * @param args - Query arguments\n * @param context - Agent context\n */\n lvpHasEntry(args: HasLinkedVPEntryArgs, context: RequiredContext): Promise<boolean>\n\n /**\n * Get LinkedVP service entries for a DID to be added to a DID Document\n * This is useful when generating DID Documents with toDidDocument\n * @param args - Query arguments for the DID\n * @param context - Agent context\n */\n lvpGetServiceEntries(args: GetServiceEntriesArgs, context: RequiredContext): Promise<Array<LinkedVPServiceEntry>>\n\n /**\n * Generate and return a Verifiable Presentation for a published LinkedVP\n * This is the main endpoint handler for GET /linked-vp/{linkedVpId}\n * @param args - Generation arguments\n * @param context - Agent context\n */\n lvpGeneratePresentation(args: GeneratePresentationArgs, context: RequiredContext): Promise<LinkedVPPresentation>\n}\n\nexport type PublishCredentialArgs = {\n digitalCredentialId: string\n linkedVpId?: string // Optional: if not provided, will be auto-generated\n}\n\nexport type UnpublishCredentialArgs = {\n linkedVpId: string\n}\n\nexport type HasLinkedVPEntryArgs = {\n linkedVpId: string\n}\n\nexport type GetServiceEntriesArgs = {\n tenantId?: string\n}\n\nexport type GeneratePresentationArgs = {\n linkedVpId: string\n}\n\nexport type LinkedVPEntry = {\n id: string\n linkedVpId: string\n linkedVpFrom?: Date\n tenantId?: string\n createdAt: Date\n}\n\nexport type LinkedVPServiceEntry = {\n id: string\n type: 'LinkedVerifiablePresentation'\n serviceEndpoint: string\n}\n\nexport type RequiredContext = IAgentContext<IIdentifierResolution & ICredentialStore & IKeyManager & VcdmCredentialPlugin & ISDJwtPlugin>\n"],"mappings":"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","names":["IsNull","Not","calculateSdHash","defaultGenerateDigest","CredentialMapper","DocumentFormat","Loggers","LOGGER_NAMESPACE","logger","Loggers","DEFAULT","get","LOGGER_NAMESPACE","CLOCK_SKEW","extractOriginalCredential","credential","udc","originalVerifiableCredential","uniformVerifiableCredential","original","createLinkedVPPresentation","holderDid","agent","debug","id","identifier","identifierManagedGet","originalCredential","documentFormat","CredentialMapper","detectDocumentType","DocumentFormat","SD_JWT_VC","decodedSdJwt","decodeSdJwtVcAsync","compactSdJwtVc","defaultGenerateDigest","hashAlg","signedPayload","_sd_alg","sdHash","calculateSdHash","kbJwtPayload","iat","Math","floor","Date","now","sd_hash","presentationResult","createSdJwtPresentation","presentation","kb","payload","presentationPayload","JSONLD","vcObject","JSON","parse","vpObject","type","verifiableCredential","holder","verifiablePresentationSP","createVerifiablePresentation","proofFormat","keyRef","kmsKeyRef","kid","MSO_MDOC","warning","vcJwt","stringify","vpPayload","iss","vp","exp","vpJwt","proof","jwt","linkedVPManagerMethods","LinkedVPManager","schema","ILinkedVPManager","methods","lvpPublishCredential","bind","lvpUnpublishCredential","lvpHasEntry","lvpGetServiceEntries","lvpGeneratePresentation","args","context","digitalCredentialId","credential","agent","crsGetCredential","id","linkedVpId","Promise","reject","Error","buildLinkedVpId","tenantId","ensureLinkedVpIdUnique","publishedAt","Date","crsUpdateCredential","linkedVpFrom","createdAt","credentials","crsGetCredentials","filter","length","undefined","error","Not","IsNull","cred","flatMap","uniformDocument","JSON","parse","holderDidForEntry","getHolderDid","startsWith","credentialToServiceEntry","parseTenantFromLinkedVpId","uniqueCredentials","crsGetUniqueCredentials","uniqueDigitalCredential","uniformVerifiableCredential","digitalCredential","holderDid","createLinkedVPPresentation","cnf","jwk","kid","split","credentialSubject","Array","isArray","idx","lastIndexOf","substring","generateLinkedVpId","Math","random","toString","finalLinkedVpId","includes","getBaseUrlFromDid","withoutPrefix","replace","parts","domain","shift","path","join","buildServiceEndpoint","baseUrl","cleanBaseUrl","endsWith","slice","type","serviceEndpoint"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sphereon/ssi-sdk.linked-vp",
|
|
3
|
-
"version": "0.34.1-feature.SSISDK.82.linkedVP.
|
|
3
|
+
"version": "0.34.1-feature.SSISDK.82.linkedVP.341+483672e1",
|
|
4
4
|
"source": "src/index.ts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
"generate-plugin-schema": "tsx ../../packages/dev/bin/sphereon.js dev generate-plugin-schema"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.34.1-feature.SSISDK.82.linkedVP.
|
|
31
|
-
"@sphereon/ssi-sdk.credential-store": "0.34.1-feature.SSISDK.82.linkedVP.
|
|
32
|
-
"@sphereon/ssi-sdk.credential-vcdm": "0.34.1-feature.SSISDK.82.linkedVP.
|
|
33
|
-
"@sphereon/ssi-sdk.data-store": "0.34.1-feature.SSISDK.82.linkedVP.
|
|
34
|
-
"@sphereon/ssi-sdk.data-store-types": "0.34.1-feature.SSISDK.82.linkedVP.
|
|
35
|
-
"@sphereon/ssi-sdk.sd-jwt": "0.34.1-feature.SSISDK.82.linkedVP.
|
|
36
|
-
"@sphereon/ssi-types": "0.34.1-feature.SSISDK.82.linkedVP.
|
|
30
|
+
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.34.1-feature.SSISDK.82.linkedVP.341+483672e1",
|
|
31
|
+
"@sphereon/ssi-sdk.credential-store": "0.34.1-feature.SSISDK.82.linkedVP.341+483672e1",
|
|
32
|
+
"@sphereon/ssi-sdk.credential-vcdm": "0.34.1-feature.SSISDK.82.linkedVP.341+483672e1",
|
|
33
|
+
"@sphereon/ssi-sdk.data-store": "0.34.1-feature.SSISDK.82.linkedVP.341+483672e1",
|
|
34
|
+
"@sphereon/ssi-sdk.data-store-types": "0.34.1-feature.SSISDK.82.linkedVP.341+483672e1",
|
|
35
|
+
"@sphereon/ssi-sdk.sd-jwt": "0.34.1-feature.SSISDK.82.linkedVP.341+483672e1",
|
|
36
|
+
"@sphereon/ssi-types": "0.34.1-feature.SSISDK.82.linkedVP.341+483672e1",
|
|
37
37
|
"@veramo/utils": "4.2.0",
|
|
38
38
|
"cross-fetch": "^4.1.0",
|
|
39
39
|
"dcql": "1.0.1",
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"uint8arrays": "3.1.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@sphereon/ssi-sdk-ext.key-manager": "0.34.1-feature.SSISDK.82.linkedVP.
|
|
46
|
-
"@sphereon/ssi-sdk-ext.kms-local": "0.34.1-feature.SSISDK.82.linkedVP.
|
|
47
|
-
"@sphereon/ssi-sdk.agent-config": "0.34.1-feature.SSISDK.82.linkedVP.
|
|
48
|
-
"@sphereon/ssi-sdk.credential-vcdm1-jwt-provider": "0.34.1-feature.SSISDK.82.linkedVP.
|
|
45
|
+
"@sphereon/ssi-sdk-ext.key-manager": "0.34.1-feature.SSISDK.82.linkedVP.341+483672e1",
|
|
46
|
+
"@sphereon/ssi-sdk-ext.kms-local": "0.34.1-feature.SSISDK.82.linkedVP.341+483672e1",
|
|
47
|
+
"@sphereon/ssi-sdk.agent-config": "0.34.1-feature.SSISDK.82.linkedVP.341+483672e1",
|
|
48
|
+
"@sphereon/ssi-sdk.credential-vcdm1-jwt-provider": "0.34.1-feature.SSISDK.82.linkedVP.341+483672e1",
|
|
49
49
|
"@veramo/data-store": "4.2.0",
|
|
50
50
|
"@veramo/did-manager": "4.2.0",
|
|
51
51
|
"@veramo/did-provider-web": "4.2.0",
|
|
@@ -77,5 +77,5 @@
|
|
|
77
77
|
"Presentation Defintion Manager",
|
|
78
78
|
"PD Manager"
|
|
79
79
|
],
|
|
80
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "483672e1d9b2891a346216a0ebea64745561d6ed"
|
|
81
81
|
}
|
|
@@ -63,7 +63,7 @@ export default (testContext: {
|
|
|
63
63
|
digitalCredentialId: credentialId,
|
|
64
64
|
})
|
|
65
65
|
|
|
66
|
-
expect(result.linkedVpId).toMatch(/^lvp
|
|
66
|
+
expect(result.linkedVpId).toMatch(/^lvp-[a-z0-9]+@tenant1$/)
|
|
67
67
|
})
|
|
68
68
|
|
|
69
69
|
it('should publish credential with custom linkedVpId AND append tenantId', async () => {
|
|
@@ -127,6 +127,15 @@ export default (testContext: {
|
|
|
127
127
|
})
|
|
128
128
|
|
|
129
129
|
it('should get service entries for default tenant (no tenantId param)', async () => {
|
|
130
|
+
// Clean up any existing published credentials first
|
|
131
|
+
const existingEntries = await agent.lvpGetServiceEntries({})
|
|
132
|
+
for (const entry of existingEntries) {
|
|
133
|
+
const linkedVpId = entry.id.split('#')[1]
|
|
134
|
+
await agent.lvpUnpublishCredential({ linkedVpId }).catch(() => {
|
|
135
|
+
// Ignore errors if already unpublished
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
130
139
|
const id1 = await createTestCredential(agent, tenantId)
|
|
131
140
|
const id2 = await createTestCredential(agent, tenantId)
|
|
132
141
|
|
|
@@ -135,17 +144,18 @@ export default (testContext: {
|
|
|
135
144
|
|
|
136
145
|
const entries = await agent.lvpGetServiceEntries({})
|
|
137
146
|
|
|
147
|
+
expect(entries).toHaveLength(2)
|
|
138
148
|
expect(entries).toEqual(
|
|
139
149
|
expect.arrayContaining([
|
|
140
150
|
{
|
|
141
|
-
id: `${
|
|
151
|
+
id: `${holderDid}#service1@tenant1`,
|
|
142
152
|
type: 'LinkedVerifiablePresentation',
|
|
143
|
-
serviceEndpoint: `https://example.com/
|
|
153
|
+
serviceEndpoint: `https://example.com/linked-vp/service1@tenant1`,
|
|
144
154
|
},
|
|
145
155
|
{
|
|
146
|
-
id: `${
|
|
156
|
+
id: `${holderDid}#service2@tenant1`,
|
|
147
157
|
type: 'LinkedVerifiablePresentation',
|
|
148
|
-
serviceEndpoint: `https://example.com/
|
|
158
|
+
serviceEndpoint: `https://example.com/linked-vp/service2@tenant1`,
|
|
149
159
|
},
|
|
150
160
|
]),
|
|
151
161
|
)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DigitalCredential } from '@sphereon/ssi-sdk.data-store-types'
|
|
2
|
+
import { type IVerifiableCredential } from '@sphereon/ssi-types'
|
|
2
3
|
import { IAgentPlugin } from '@veramo/core'
|
|
3
4
|
import { IsNull, Not } from 'typeorm'
|
|
4
5
|
import { schema } from '../index'
|
|
@@ -38,12 +39,6 @@ export class LinkedVPManager implements IAgentPlugin {
|
|
|
38
39
|
lvpGeneratePresentation: this.lvpGeneratePresentation.bind(this),
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
private readonly holderDids: Record<string, string>
|
|
42
|
-
|
|
43
|
-
constructor(options: { holderDids: Record<string, string> }) {
|
|
44
|
-
this.holderDids = options.holderDids
|
|
45
|
-
}
|
|
46
|
-
|
|
47
42
|
private async lvpPublishCredential(args: PublishCredentialArgs, context: RequiredContext): Promise<LinkedVPEntry> {
|
|
48
43
|
const { digitalCredentialId } = args
|
|
49
44
|
|
|
@@ -122,16 +117,16 @@ export class LinkedVPManager implements IAgentPlugin {
|
|
|
122
117
|
|
|
123
118
|
return credentials
|
|
124
119
|
.filter((cred) => cred.linkedVpId !== undefined && cred.linkedVpId !== null)
|
|
125
|
-
.
|
|
126
|
-
const
|
|
127
|
-
|
|
120
|
+
.flatMap((cred) => {
|
|
121
|
+
const uniformDocument = JSON.parse(cred.uniformDocument) as IVerifiableCredential
|
|
122
|
+
const holderDidForEntry = this.getHolderDid(uniformDocument)
|
|
123
|
+
return holderDidForEntry && holderDidForEntry.startsWith('did:web') ? [this.credentialToServiceEntry(cred, holderDidForEntry)] : []
|
|
128
124
|
})
|
|
129
125
|
}
|
|
130
126
|
|
|
131
127
|
private async lvpGeneratePresentation(args: GeneratePresentationArgs, context: RequiredContext): Promise<LinkedVPPresentation> {
|
|
132
128
|
const { linkedVpId } = args
|
|
133
129
|
const tenantId = this.parseTenantFromLinkedVpId(linkedVpId)
|
|
134
|
-
const holderDid = this.getHolderDid(tenantId)
|
|
135
130
|
|
|
136
131
|
const uniqueCredentials = await context.agent.crsGetUniqueCredentials({
|
|
137
132
|
filter: [
|
|
@@ -148,16 +143,37 @@ export class LinkedVPManager implements IAgentPlugin {
|
|
|
148
143
|
return Promise.reject(Error(`Multiple credentials found for linkedVpId ${linkedVpId}`))
|
|
149
144
|
}
|
|
150
145
|
|
|
146
|
+
const uniqueDigitalCredential = uniqueCredentials[0]
|
|
147
|
+
if (!uniqueDigitalCredential.uniformVerifiableCredential) {
|
|
148
|
+
return Promise.reject(Error(`uniformVerifiableCredential could not be found for credential ${uniqueDigitalCredential.digitalCredential.id}`))
|
|
149
|
+
}
|
|
150
|
+
const holderDid = this.getHolderDid(uniqueDigitalCredential.uniformVerifiableCredential)
|
|
151
|
+
if (!holderDid) {
|
|
152
|
+
return Promise.reject(Error(`Could not extract the holder did:web from cnf nor the credentialSubject id`))
|
|
153
|
+
}
|
|
154
|
+
|
|
151
155
|
// Generate the Verifiable Presentation with all published credentials
|
|
152
|
-
return createLinkedVPPresentation(holderDid,
|
|
156
|
+
return createLinkedVPPresentation(holderDid, uniqueDigitalCredential, context.agent)
|
|
153
157
|
}
|
|
154
158
|
|
|
155
|
-
private getHolderDid(
|
|
156
|
-
|
|
157
|
-
if (
|
|
158
|
-
|
|
159
|
+
private getHolderDid(uniformDocument: IVerifiableCredential): string | undefined {
|
|
160
|
+
// Determine holder DID for identifier resolution
|
|
161
|
+
if ('cnf' in uniformDocument && 'jwk' in uniformDocument.cnf && 'kid' in uniformDocument.cnf.jwk) {
|
|
162
|
+
return uniformDocument.cnf.jwk.kid.split('#')[0]
|
|
159
163
|
}
|
|
160
|
-
|
|
164
|
+
|
|
165
|
+
if ('credentialSubject' in uniformDocument) {
|
|
166
|
+
const credentialSubject = Array.isArray(uniformDocument.credentialSubject)
|
|
167
|
+
? uniformDocument.credentialSubject[0]
|
|
168
|
+
: uniformDocument.credentialSubject
|
|
169
|
+
if ('id' in credentialSubject && credentialSubject.id) {
|
|
170
|
+
if (credentialSubject.id.startsWith('did:web')) {
|
|
171
|
+
return credentialSubject.id
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return undefined
|
|
161
177
|
}
|
|
162
178
|
|
|
163
179
|
private parseTenantFromLinkedVpId(linkedVpId: string): string | undefined {
|