@sphereon/ssi-sdk.linked-vp 0.34.1-feature.SSISDK.82.linkedVP.325
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/LICENSE +201 -0
- package/dist/index.cjs +463 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +447 -0
- package/dist/index.d.ts +447 -0
- package/dist/index.js +442 -0
- package/dist/index.js.map +1 -0
- package/package.json +80 -0
- package/plugin.schema.json +183 -0
- package/src/__tests__/localAgent.test.ts +95 -0
- package/src/__tests__/shared/linkedVPManagerAgentLogic.ts +170 -0
- package/src/agent/LinkedVPManager.ts +221 -0
- package/src/index.ts +7 -0
- package/src/services/LinkedVPService.ts +84 -0
- package/src/types/ILinkedVPManager.ts +85 -0
- package/src/types/index.ts +1 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { UniqueDigitalCredential } from '@sphereon/ssi-sdk.credential-store'
|
|
2
|
+
import { Loggers, OriginalVerifiableCredential, WrappedVerifiableCredential } from '@sphereon/ssi-types'
|
|
3
|
+
import type { PresentationPayload } from '@veramo/core'
|
|
4
|
+
import { W3CVerifiableCredential } from '@veramo/core/src/types/vc-data-model'
|
|
5
|
+
import { LOGGER_NAMESPACE, RequiredContext } from '../types'
|
|
6
|
+
|
|
7
|
+
const logger = Loggers.DEFAULT.get(LOGGER_NAMESPACE)
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Extracts the original credential from various wrapper types
|
|
11
|
+
*/
|
|
12
|
+
function extractOriginalCredential(
|
|
13
|
+
credential: UniqueDigitalCredential | WrappedVerifiableCredential | OriginalVerifiableCredential,
|
|
14
|
+
): OriginalVerifiableCredential {
|
|
15
|
+
if (typeof credential === 'string') {
|
|
16
|
+
return credential
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if ('digitalCredential' in credential) {
|
|
20
|
+
const udc = credential as UniqueDigitalCredential
|
|
21
|
+
if (udc.originalVerifiableCredential) {
|
|
22
|
+
return udc.originalVerifiableCredential
|
|
23
|
+
}
|
|
24
|
+
return udc.uniformVerifiableCredential as OriginalVerifiableCredential
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if ('original' in credential) {
|
|
28
|
+
return credential.original
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return credential as OriginalVerifiableCredential
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Creates a Verifiable Presentation for LinkedVP publishing
|
|
36
|
+
* Contains multiple credentials in a single JWT VP
|
|
37
|
+
* No nonce or audience since this is for publishing, not responding to verification
|
|
38
|
+
*/
|
|
39
|
+
export async function createLinkedVPPresentation(
|
|
40
|
+
holderDid: string,
|
|
41
|
+
credentials: UniqueDigitalCredential[],
|
|
42
|
+
agent: RequiredContext['agent'],
|
|
43
|
+
): Promise<string | Record<string, any>> {
|
|
44
|
+
if (credentials.length === 0) {
|
|
45
|
+
return Promise.reject(Error('Cannot create LinkedVP presentation with zero credentials'))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
logger.debug(`Creating LinkedVP presentation for ${holderDid} with ${credentials.length} credentials`)
|
|
49
|
+
|
|
50
|
+
const identifier = await agent.identifierManagedGet({ identifier: holderDid })
|
|
51
|
+
|
|
52
|
+
// Extract and prepare credentials
|
|
53
|
+
const verifiableCredentials = credentials.map((credential) => {
|
|
54
|
+
const original = extractOriginalCredential(credential)
|
|
55
|
+
// Keep as-is if string (JWT), otherwise convert to object
|
|
56
|
+
return typeof original === 'string' ? original : original
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
// Create VP structure
|
|
60
|
+
const vpObject: PresentationPayload = {
|
|
61
|
+
'@context': ['https://www.w3.org/2018/credentials/v1'],
|
|
62
|
+
type: ['VerifiablePresentation'],
|
|
63
|
+
holder: holderDid,
|
|
64
|
+
verifiableCredential: verifiableCredentials as W3CVerifiableCredential[],
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Create and sign the VP as JWT
|
|
68
|
+
const result = await agent.createVerifiablePresentation({
|
|
69
|
+
presentation: vpObject,
|
|
70
|
+
proofFormat: 'jwt',
|
|
71
|
+
keyRef: identifier.kmsKeyRef || identifier.kid,
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
// Extract JWT from result
|
|
75
|
+
if (typeof result === 'string') {
|
|
76
|
+
return result
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (result.proof && 'jws' in result.proof) {
|
|
80
|
+
return result.proof.jws
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return Promise.reject(Error('Failed to create JWT VP - no JWT in result'))
|
|
84
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
2
|
+
import { ICredentialStore } from '@sphereon/ssi-sdk.credential-store'
|
|
3
|
+
import { VcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'
|
|
4
|
+
import { IAgentContext, IPluginMethodMap } from '@veramo/core'
|
|
5
|
+
import { IKeyManager } from '@veramo/core/src/types/IKeyManager'
|
|
6
|
+
|
|
7
|
+
export const LOGGER_NAMESPACE = 'sphereon:linked-vp'
|
|
8
|
+
|
|
9
|
+
export type LinkedVPPresentation = string | Record<string, any>
|
|
10
|
+
|
|
11
|
+
export interface ILinkedVPManager extends IPluginMethodMap {
|
|
12
|
+
/**
|
|
13
|
+
* Publish a credential as a LinkedVP by adding it to the holder's DID Document
|
|
14
|
+
* @param args - Publication arguments including credential ID and scope configuration
|
|
15
|
+
* @param context - Agent context
|
|
16
|
+
*/
|
|
17
|
+
lvpPublishCredential(args: PublishCredentialArgs, context: RequiredContext): Promise<LinkedVPEntry>
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Unpublish a credential by removing its LinkedVP entry from the DID Document
|
|
21
|
+
* @param args - Unpublish arguments
|
|
22
|
+
* @param context - Agent context
|
|
23
|
+
*/
|
|
24
|
+
lvpUnpublishCredential(args: UnpublishCredentialArgs, context: RequiredContext): Promise<boolean>
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Check if a LinkedVP entry exists by linkedVpId
|
|
28
|
+
* @param args - Query arguments
|
|
29
|
+
* @param context - Agent context
|
|
30
|
+
*/
|
|
31
|
+
lvpHasEntry(args: HasLinkedVPEntryArgs, context: RequiredContext): Promise<boolean>
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get LinkedVP service entries for a DID to be added to a DID Document
|
|
35
|
+
* This is useful when generating DID Documents with toDidDocument
|
|
36
|
+
* @param args - Query arguments for the DID
|
|
37
|
+
* @param context - Agent context
|
|
38
|
+
*/
|
|
39
|
+
lvpGetServiceEntries(args: GetServiceEntriesArgs, context: RequiredContext): Promise<Array<LinkedVPServiceEntry>>
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Generate and return a Verifiable Presentation for a published LinkedVP
|
|
43
|
+
* This is the main endpoint handler for GET /linked-vp/{linkedVpId}
|
|
44
|
+
* @param args - Generation arguments
|
|
45
|
+
* @param context - Agent context
|
|
46
|
+
*/
|
|
47
|
+
lvpGeneratePresentation(args: GeneratePresentationArgs, context: RequiredContext): Promise<LinkedVPPresentation>
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type PublishCredentialArgs = {
|
|
51
|
+
digitalCredentialId: string
|
|
52
|
+
linkedVpId?: string // Optional: if not provided, will be auto-generated
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type UnpublishCredentialArgs = {
|
|
56
|
+
linkedVpId: string
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export type HasLinkedVPEntryArgs = {
|
|
60
|
+
linkedVpId: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export type GetServiceEntriesArgs = {
|
|
64
|
+
tenantId?: string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type GeneratePresentationArgs = {
|
|
68
|
+
linkedVpId: string
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export type LinkedVPEntry = {
|
|
72
|
+
id: string
|
|
73
|
+
linkedVpId: string
|
|
74
|
+
tenantId?: string
|
|
75
|
+
linkedVpFrom?: Date
|
|
76
|
+
createdAt: Date
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export type LinkedVPServiceEntry = {
|
|
80
|
+
id: string
|
|
81
|
+
type: 'LinkedVerifiablePresentation'
|
|
82
|
+
serviceEndpoint: string
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export type RequiredContext = IAgentContext<IIdentifierResolution & ICredentialStore & IKeyManager & VcdmCredentialPlugin>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ILinkedVPManager'
|