@sphereon/ssi-sdk.vc-status-list 0.34.1-feature.SSISDK.17.bitstring.sl.11 → 0.34.1-feature.SSISDK.17.bitstring.sl.13

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sphereon/ssi-sdk.vc-status-list",
3
3
  "description": "Sphereon SSI-SDK plugin for Status List management, like StatusList2021.",
4
- "version": "0.34.1-feature.SSISDK.17.bitstring.sl.11+b492941c",
4
+ "version": "0.34.1-feature.SSISDK.17.bitstring.sl.13+61bcf6d3",
5
5
  "source": "src/index.ts",
6
6
  "type": "module",
7
7
  "main": "./dist/index.cjs",
@@ -31,8 +31,9 @@
31
31
  "@sphereon/ssi-sdk-ext.did-utils": "0.29.0",
32
32
  "@sphereon/ssi-sdk-ext.identifier-resolution": "0.29.0",
33
33
  "@sphereon/ssi-sdk-ext.jwt-service": "0.29.0",
34
- "@sphereon/ssi-sdk.data-store": "0.34.1-feature.SSISDK.17.bitstring.sl.11+b492941c",
35
- "@sphereon/ssi-types": "0.34.1-feature.SSISDK.17.bitstring.sl.11+b492941c",
34
+ "@sphereon/ssi-sdk.credential-vcdm": "0.34.1-feature.SSISDK.17.bitstring.sl.13+61bcf6d3",
35
+ "@sphereon/ssi-sdk.data-store": "0.34.1-feature.SSISDK.17.bitstring.sl.13+61bcf6d3",
36
+ "@sphereon/ssi-types": "0.34.1-feature.SSISDK.17.bitstring.sl.13+61bcf6d3",
36
37
  "@sphereon/vc-status-list": "7.0.0-next.0",
37
38
  "@veramo/core": "4.2.0",
38
39
  "@veramo/credential-status": "4.2.0",
@@ -71,5 +72,5 @@
71
72
  "SSI",
72
73
  "StatusList2021"
73
74
  ],
74
- "gitHead": "b492941ccbdde19ae30ec024956ca9f6f336a699"
75
+ "gitHead": "61bcf6d37bcb3d77036b5415d72853c3ba3f9273"
75
76
  }
package/src/functions.ts CHANGED
@@ -2,13 +2,12 @@ import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-res
2
2
  import {
3
3
  CredentialMapper,
4
4
  type CredentialProofFormat,
5
- DocumentFormat,
6
5
  type StatusListCredential,
7
6
  StatusListDriverType,
8
7
  StatusListType,
9
8
  type StatusPurpose2021,
10
9
  } from '@sphereon/ssi-types'
11
- import type { CredentialStatus, DIDDocument, IAgentContext, ICredentialPlugin, ProofFormat as VeramoProofFormat } from '@veramo/core'
10
+ import type { CredentialStatus, DIDDocument, IAgentContext, ProofFormat as VeramoProofFormat } from '@veramo/core'
12
11
 
13
12
  import { IAddStatusListArgs, IBitstringStatusListEntryEntity, IStatusListEntryEntity, StatusListEntity } from '@sphereon/ssi-sdk.data-store'
14
13
 
@@ -31,6 +30,7 @@ import {
31
30
  } from './types'
32
31
  import { assertValidProofType, determineStatusListType, getAssertedValue, getAssertedValues } from './utils'
33
32
  import { getStatusListImplementation } from './impl/StatusListFactory'
33
+ import { IVcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'
34
34
 
35
35
  export async function fetchStatusListCredential(args: { statusListCredential: string }): Promise<StatusListCredential> {
36
36
  const url = getAssertedValue('statusListCredential', args.statusListCredential)
@@ -164,7 +164,7 @@ export async function checkStatusIndexFromStatusListCredential(args: {
164
164
 
165
165
  export async function createNewStatusList(
166
166
  args: CreateNewStatusListFuncArgs,
167
- context: IAgentContext<(ICredentialPlugin | any) /*IvcdMCredentialPlugin is not available*/ & IIdentifierResolution>,
167
+ context: IAgentContext<(IVcdmCredentialPlugin | any) /*IvcdMCredentialPlugin is not available*/ & IIdentifierResolution>,
168
168
  ): Promise<StatusListResult> {
169
169
  const { type } = getAssertedValues(args)
170
170
  const implementation = getStatusListImplementation(type)
@@ -173,7 +173,7 @@ export async function createNewStatusList(
173
173
 
174
174
  export async function updateStatusIndexFromStatusListCredential(
175
175
  args: UpdateStatusListIndexArgs,
176
- context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
176
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
177
177
  ): Promise<StatusListResult> {
178
178
  const credential = getAssertedValue('statusListCredential', args.statusListCredential)
179
179
  const statusListType: StatusListType = determineStatusListType(credential)
@@ -182,40 +182,19 @@ export async function updateStatusIndexFromStatusListCredential(
182
182
  }
183
183
 
184
184
  export async function statusListCredentialToDetails({
185
+ statusListType,
185
186
  correlationId,
186
187
  driverType,
187
188
  statusListCredential,
188
189
  bitsPerStatus,
189
190
  }: {
191
+ statusListType: StatusListType
190
192
  statusListCredential: StatusListCredential
191
193
  correlationId?: string
192
194
  driverType?: StatusListDriverType
193
195
  bitsPerStatus?: number
194
196
  }): Promise<StatusListResult & Partial<IAddStatusListArgs>> {
195
197
  const credential = getAssertedValue('statusListCredential', statusListCredential)
196
-
197
- let statusListType: StatusListType | undefined
198
- const documentFormat = CredentialMapper.detectDocumentType(credential)
199
- if (documentFormat === DocumentFormat.JWT) {
200
- const [header] = credential.split('.')
201
- const decodedHeader = JSON.parse(Buffer.from(header, 'base64').toString())
202
-
203
- if (decodedHeader.typ === 'statuslist+jwt') {
204
- statusListType = StatusListType.OAuthStatusList
205
- }
206
- } else if (documentFormat === DocumentFormat.MSO_MDOC) {
207
- statusListType = StatusListType.OAuthStatusList
208
- // TODO check CBOR content?
209
- }
210
- if (!statusListType) {
211
- const uniform = CredentialMapper.toUniformCredential(credential)
212
- const type = uniform.type.find((t) => t.includes('StatusList2021') || t.includes('OAuth2StatusList') || t.includes('BitstringStatusList'))
213
- if (!type) {
214
- throw new Error('Invalid status list credential type')
215
- }
216
- statusListType = type.replace('Credential', '') as StatusListType
217
- }
218
-
219
198
  const implementation = getStatusListImplementation(statusListType)
220
199
 
221
200
  // The implementation should now return all the type-specific fields needed for the entity
@@ -250,7 +229,7 @@ export async function createCredentialStatusFromStatusList(args: {
250
229
 
251
230
  export async function updateStatusListIndexFromEncodedList(
252
231
  args: UpdateStatusListFromEncodedListArgs,
253
- context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
232
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
254
233
  ): Promise<StatusListResult> {
255
234
  const { type } = getAssertedValue('type', args)
256
235
  const implementation = getStatusListImplementation(type!)
@@ -259,7 +238,7 @@ export async function updateStatusListIndexFromEncodedList(
259
238
 
260
239
  export async function statusList2021ToVerifiableCredential(
261
240
  args: StatusList2021ToVerifiableCredentialArgs,
262
- context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
241
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
263
242
  ): Promise<StatusListCredential> {
264
243
  const { issuer, id, type } = getAssertedValues(args)
265
244
  const identifier = await context.agent.identifierManagedGet({
@@ -1,4 +1,22 @@
1
- import type { IAgentContext, ICredentialPlugin, ProofFormat as VeramoProofFormat } from '@veramo/core'
1
+ /**
2
+ * Bitstring Status List Implementation
3
+ *
4
+ * This module implements the W3C Bitstring Status List specification for managing
5
+ * credential status information. It provides functionality to create, update, and
6
+ * check the status of verifiable credentials using compressed bitstring status lists.
7
+ *
8
+ * Key features:
9
+ * - Create new bitstring status lists with configurable purposes and bit sizes
10
+ * - Update individual credential status entries in existing lists
11
+ * - Check the status of specific credentials by index
12
+ * - Support for multiple proof formats (JWT, LDS, CBOR)
13
+ * - Integration with Veramo agent context for credential signing
14
+ *
15
+ * @author Sphereon International B.V.
16
+ * @since 2024
17
+ */
18
+
19
+ import type { IAgentContext } from '@veramo/core'
2
20
  import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
3
21
 
4
22
  import {
@@ -24,17 +42,37 @@ import {
24
42
 
25
43
  import { assertValidProofType, ensureDate, getAssertedProperty, getAssertedValue, getAssertedValues } from '../utils'
26
44
  import { BitstringStatusListCredential } from '../types/BitstringStatusList'
27
- import { BitstreamStatusList, BitstringStatusPurpose, createStatusListCredential } from '@4sure-tech/vc-bitstring-status-lists'
45
+ import {
46
+ BitstreamStatusList,
47
+ BitstringStatusListCredentialUnsigned,
48
+ BitstringStatusPurpose,
49
+ createStatusListCredential,
50
+ } from '@4sure-tech/vc-bitstring-status-lists'
28
51
  import { BitstringStatusListEntity, IBitstringStatusListEntryEntity, IStatusListEntryEntity, StatusListEntity } from '@sphereon/ssi-sdk.data-store'
52
+ import { IVcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'
29
53
 
30
54
  export const DEFAULT_LIST_LENGTH = 131072 // W3C spec minimum
31
55
  export const DEFAULT_PROOF_FORMAT = 'lds' as CredentialProofFormat
32
56
  export const DEFAULT_STATUS_PURPOSE: BitstringStatusPurpose = 'revocation'
33
57
 
58
+ /**
59
+ * Implementation of the IStatusList interface for W3C Bitstring Status Lists
60
+ *
61
+ * This class handles the creation, updating, and verification of bitstring status lists
62
+ * according to the W3C Bitstring Status List specification. It supports multiple
63
+ * status purposes (revocation, suspension, etc.) and various proof formats.
64
+ */
34
65
  export class BitstringStatusListImplementation implements IStatusList {
66
+ /**
67
+ * Creates a new bitstring status list with the specified configuration
68
+ *
69
+ * @param args - Configuration for the new status list including issuer, purpose, and size
70
+ * @param context - Veramo agent context for credential operations
71
+ * @returns Promise resolving to the created status list details
72
+ */
35
73
  async createNewStatusList(
36
74
  args: CreateStatusListArgs,
37
- context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
75
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
38
76
  ): Promise<StatusListResult> {
39
77
  if (!args.bitstringStatusList) {
40
78
  throw new Error('BitstringStatusList options are required for type BitstringStatusList')
@@ -43,30 +81,37 @@ export class BitstringStatusListImplementation implements IStatusList {
43
81
  const length = args?.length ?? DEFAULT_LIST_LENGTH
44
82
  const proofFormat: CredentialProofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT
45
83
  assertValidProofType(StatusListType.BitstringStatusList, proofFormat)
46
- const veramoProofFormat: VeramoProofFormat = proofFormat as VeramoProofFormat
47
84
 
48
85
  const { issuer, id } = args
49
86
  const correlationId = getAssertedValue('correlationId', args.correlationId)
50
87
  const { statusPurpose, bitsPerStatus, validFrom, validUntil, ttl } = args.bitstringStatusList
88
+
89
+ const unsignedCredential: BitstringStatusListCredentialUnsigned = await createStatusListCredential({
90
+ id,
91
+ issuer,
92
+ statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
93
+ validFrom: ensureDate(validFrom),
94
+ validUntil: ensureDate(validUntil),
95
+ ttl,
96
+ })
51
97
  const statusListCredential = await this.createVerifiableCredential(
52
98
  {
53
- ...args,
54
- proofFormat: veramoProofFormat,
55
- statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
56
- validFrom: ensureDate(validFrom),
57
- validUntil: ensureDate(validUntil),
58
- ttl,
99
+ unsignedCredential,
100
+ id,
101
+ issuer,
102
+ proofFormat,
103
+ keyRef: args.keyRef,
59
104
  },
60
105
  context,
61
106
  )
62
107
 
63
108
  return {
64
- encodedList: statusListCredential.credentialSubject.encodedList,
65
- statusListCredential: statusListCredential,
109
+ encodedList: unsignedCredential.credentialSubject.encodedList,
110
+ statusListCredential,
66
111
  bitstringStatusList: {
67
112
  statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
68
- ...(statusListCredential.validFrom && { validFrom: new Date(statusListCredential.validFrom) }),
69
- ...(statusListCredential.validUntil && { validUntil: new Date(statusListCredential.validUntil) }),
113
+ ...(unsignedCredential.validFrom && { validFrom: new Date(unsignedCredential.validFrom) }),
114
+ ...(unsignedCredential.validUntil && { validUntil: new Date(unsignedCredential.validUntil) }),
70
115
  ttl,
71
116
  bitsPerStatus,
72
117
  },
@@ -80,12 +125,19 @@ export class BitstringStatusListImplementation implements IStatusList {
80
125
  }
81
126
  }
82
127
 
128
+ /**
129
+ * Updates the status of a specific credential in an existing status list
130
+ *
131
+ * @param args - Update parameters including the status list credential, index, and new value
132
+ * @param context - Veramo agent context for credential operations
133
+ * @returns Promise resolving to the updated status list details
134
+ */
83
135
  async updateStatusListIndex(
84
136
  args: UpdateStatusListIndexArgs,
85
- context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
137
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
86
138
  ): Promise<StatusListResult> {
87
139
  if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
88
- return Promise.reject('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListIndex)')
140
+ return Promise.reject(Error('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListIndex)'))
89
141
  }
90
142
 
91
143
  const credential = args.statusListCredential
@@ -108,74 +160,92 @@ export class BitstringStatusListImplementation implements IStatusList {
108
160
  const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : undefined
109
161
  const ttl = credSubject.ttl
110
162
 
163
+ const unsignedCredential: BitstringStatusListCredentialUnsigned = await createStatusListCredential({
164
+ id,
165
+ issuer,
166
+ statusList,
167
+ statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
168
+ validFrom: ensureDate(validFrom),
169
+ validUntil: ensureDate(validUntil),
170
+ ttl,
171
+ })
172
+
111
173
  const updatedCredential = await this.createVerifiableCredential(
112
174
  {
113
- ...args,
175
+ unsignedCredential,
114
176
  id,
115
177
  issuer,
116
- statusList,
117
- proofFormat: proofFormat,
118
- statusPurpose,
119
- ttl,
120
- validFrom,
121
- validUntil,
178
+ proofFormat,
179
+ keyRef: args.keyRef,
122
180
  },
123
181
  context,
124
182
  )
125
183
 
126
184
  return {
127
185
  statusListCredential: updatedCredential,
128
- encodedList: updatedCredential.credentialSubject.encodedList,
186
+ encodedList: unsignedCredential.credentialSubject.encodedList,
129
187
  bitstringStatusList: {
130
188
  statusPurpose,
131
- ...(updatedCredential.validFrom && { validFrom: new Date(updatedCredential.validFrom) }),
132
- ...(updatedCredential.validUntil && { validUntil: new Date(updatedCredential.validUntil) }),
189
+ ...(unsignedCredential.validFrom && { validFrom: new Date(unsignedCredential.validFrom) }),
190
+ ...(unsignedCredential.validUntil && { validUntil: new Date(unsignedCredential.validUntil) }),
133
191
  bitsPerStatus: args.bitsPerStatus,
134
192
  ttl,
135
193
  },
136
194
  length: statusList.getLength(),
137
195
  type: StatusListType.BitstringStatusList,
138
- proofFormat: proofFormat,
196
+ proofFormat,
139
197
  id,
140
198
  issuer,
141
199
  statuslistContentType: this.buildContentType(proofFormat),
142
200
  }
143
201
  }
144
202
 
203
+ /**
204
+ * Updates a status list by decoding an encoded list, modifying it, and re-encoding
205
+ *
206
+ * @param args - Update parameters including encoded list, index, and new value
207
+ * @param context - Veramo agent context for credential operations
208
+ * @returns Promise resolving to the updated status list details
209
+ */
145
210
  async updateStatusListFromEncodedList(
146
211
  args: UpdateStatusListFromEncodedListArgs,
147
- context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
212
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
148
213
  ): Promise<StatusListResult> {
149
214
  if (!args.bitstringStatusList) {
150
215
  throw new Error('bitstringStatusList options required for type BitstringStatusList')
151
216
  }
152
217
 
153
218
  if (args.bitstringStatusList.bitsPerStatus < 1) {
154
- return Promise.reject('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListFromEncodedList)')
219
+ return Promise.reject(Error('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListFromEncodedList)'))
155
220
  }
156
221
 
157
222
  const { statusPurpose, bitsPerStatus, ttl, validFrom, validUntil } = args.bitstringStatusList
158
223
 
159
224
  const proofFormat: CredentialProofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT
160
225
  assertValidProofType(StatusListType.BitstringStatusList, proofFormat)
161
- const veramoProofFormat: VeramoProofFormat = proofFormat as VeramoProofFormat
162
226
 
163
227
  const { issuer, id } = getAssertedValues(args)
164
228
  const statusList: BitstreamStatusList = await BitstreamStatusList.decode({ encodedList: args.encodedList, statusSize: bitsPerStatus })
165
229
  const index = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
166
230
  statusList.setStatus(index, args.value)
167
231
 
232
+ const unsignedCredential: BitstringStatusListCredentialUnsigned = await createStatusListCredential({
233
+ id,
234
+ issuer,
235
+ statusList,
236
+ statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
237
+ validFrom: ensureDate(validFrom),
238
+ validUntil: ensureDate(validUntil),
239
+ ttl,
240
+ })
241
+
168
242
  const credential = await this.createVerifiableCredential(
169
243
  {
244
+ unsignedCredential,
170
245
  id,
171
246
  issuer,
172
- statusList,
173
- proofFormat: veramoProofFormat,
247
+ proofFormat,
174
248
  keyRef: args.keyRef,
175
- statusPurpose,
176
- validFrom: ensureDate(validFrom),
177
- validUntil: ensureDate(validUntil),
178
- ttl,
179
249
  },
180
250
  context,
181
251
  )
@@ -183,34 +253,38 @@ export class BitstringStatusListImplementation implements IStatusList {
183
253
  return {
184
254
  type: StatusListType.BitstringStatusList,
185
255
  statusListCredential: credential,
186
- encodedList: credential.credentialSubject.encodedList,
256
+ encodedList: unsignedCredential.credentialSubject.encodedList,
187
257
  bitstringStatusList: {
188
258
  statusPurpose,
189
259
  bitsPerStatus,
190
- ...(credential.validFrom && { validFrom: new Date(credential.validFrom) }),
191
- ...(credential.validUntil && { validUntil: new Date(credential.validUntil) }),
260
+ ...(unsignedCredential.validFrom && { validFrom: new Date(unsignedCredential.validFrom) }),
261
+ ...(unsignedCredential.validUntil && { validUntil: new Date(unsignedCredential.validUntil) }),
192
262
  ttl,
193
263
  },
194
264
  length: statusList.getLength(),
195
265
  proofFormat: args.proofFormat ?? 'lds',
196
- id: id,
197
- issuer: issuer,
266
+ id,
267
+ issuer,
198
268
  statuslistContentType: this.buildContentType(proofFormat),
199
269
  }
200
270
  }
201
271
 
272
+ /**
273
+ * Checks the status of a specific credential by its index in the status list
274
+ *
275
+ * @param args - Check parameters including the status list credential and index
276
+ * @returns Promise resolving to the status value at the specified index
277
+ */
202
278
  async checkStatusIndex(args: CheckStatusIndexArgs): Promise<BitstringStatus> {
203
279
  if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
204
- return Promise.reject('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (checkStatusIndex)')
280
+ return Promise.reject(Error('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (checkStatusIndex)'))
205
281
  }
206
282
 
207
283
  const uniform = CredentialMapper.toUniformCredential(args.statusListCredential)
208
284
  const { credentialSubject } = uniform
209
285
  const encodedList = getAssertedProperty('encodedList', credentialSubject)
210
286
 
211
- const statusSize = args.bitsPerStatus
212
- const statusList = await BitstreamStatusList.decode({ encodedList, statusSize })
213
-
287
+ const statusList = await BitstreamStatusList.decode({ encodedList, statusSize: args.bitsPerStatus })
214
288
  const numIndex = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
215
289
  if (statusList.getLength() <= numIndex) {
216
290
  throw new Error(`Status list index out of bounds, has ${statusList.getLength()} entries, requested ${numIndex}`)
@@ -218,17 +292,23 @@ export class BitstringStatusListImplementation implements IStatusList {
218
292
  return statusList.getStatus(numIndex)
219
293
  }
220
294
 
295
+ /**
296
+ * Converts a status list credential payload to detailed status list information
297
+ *
298
+ * @param args - Conversion parameters including the status list payload
299
+ * @returns Promise resolving to detailed status list information
300
+ */
221
301
  async toStatusListDetails(args: ToStatusListDetailsArgs): Promise<StatusListResult & IBitstringStatusListImplementationResult> {
222
302
  const { statusListPayload, bitsPerStatus } = args
223
303
  if (!bitsPerStatus || bitsPerStatus < 1) {
224
- return Promise.reject('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (toStatusListDetails)')
304
+ return Promise.reject(Error('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (toStatusListDetails)'))
225
305
  }
226
306
 
227
307
  const uniform = CredentialMapper.toUniformCredential(statusListPayload)
228
308
  const { issuer, credentialSubject } = uniform
229
309
  const id = getAssertedValue('id', uniform.id)
230
310
  const encodedList = getAssertedProperty('encodedList', credentialSubject)
231
- const proofFormat: CredentialProofFormat = CredentialMapper.detectDocumentType(statusListPayload) === DocumentFormat.JWT ? 'jwt' : 'lds'
311
+ const proofFormat: CredentialProofFormat = CredentialMapper.detectDocumentType(statusListPayload) === DocumentFormat.JWT ? 'vc+jwt' : 'lds'
232
312
  const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject
233
313
  const statusPurpose = getAssertedProperty('statusPurpose', credSubject)
234
314
  const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : undefined
@@ -271,6 +351,12 @@ export class BitstringStatusListImplementation implements IStatusList {
271
351
  }
272
352
  }
273
353
 
354
+ /**
355
+ * Creates a credential status entry for a specific credential in a status list
356
+ *
357
+ * @param args - Parameters including the status list, entry details, and index
358
+ * @returns Promise resolving to the credential status entry
359
+ */
274
360
  async createCredentialStatus(args: {
275
361
  statusList: StatusListEntity
276
362
  statusListEntry: IStatusListEntryEntity | IBitstringStatusListEntryEntity
@@ -300,44 +386,55 @@ export class BitstringStatusListImplementation implements IStatusList {
300
386
  } satisfies BitstringStatusListEntryCredentialStatus
301
387
  }
302
388
 
389
+ /**
390
+ * Creates a signed verifiable credential from an unsigned status list credential
391
+ *
392
+ * @param args - Parameters including the unsigned credential and signing details
393
+ * @param context - Veramo agent context for credential operations
394
+ * @returns Promise resolving to the signed credential
395
+ */
303
396
  private async createVerifiableCredential(
304
397
  args: {
398
+ unsignedCredential: BitstringStatusListCredentialUnsigned
305
399
  id: string
306
400
  issuer: string | IIssuer
307
- statusList?: BitstreamStatusList
308
- proofFormat: VeramoProofFormat
309
- statusPurpose: BitstringStatusPurpose
310
- validFrom?: Date
311
- validUntil?: Date
312
- ttl?: number
401
+ proofFormat: CredentialProofFormat
313
402
  keyRef?: string
314
403
  },
315
- context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
404
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
316
405
  ): Promise<BitstringStatusListCredential> {
406
+ const { unsignedCredential, issuer, proofFormat, keyRef } = args
407
+
317
408
  const identifier = await context.agent.identifierManagedGet({
318
- identifier: typeof args.issuer === 'string' ? args.issuer : args.issuer.id,
409
+ identifier: typeof issuer === 'string' ? issuer : issuer.id,
319
410
  vmRelationship: 'assertionMethod',
320
411
  offlineWhenNoDIDRegistered: true,
321
412
  })
322
413
 
323
- const unsignedCredential = await createStatusListCredential(args)
324
-
325
414
  const verifiableCredential = await context.agent.createVerifiableCredential({
326
415
  credential: unsignedCredential,
327
- keyRef: args.keyRef ?? identifier.kmsKeyRef,
328
- proofFormat: args.proofFormat,
416
+ keyRef: keyRef ?? identifier.kmsKeyRef,
417
+ proofFormat,
329
418
  fetchRemoteContexts: true,
330
419
  })
331
420
 
332
421
  return CredentialMapper.toWrappedVerifiableCredential(verifiableCredential as StatusListCredential).original as BitstringStatusListCredential
333
422
  }
334
423
 
335
- private buildContentType(proofFormat: CredentialProofFormat | undefined) {
424
+ /**
425
+ * Builds the appropriate content type string for a given proof format
426
+ *
427
+ * @param proofFormat - The proof format to build content type for
428
+ * @returns The corresponding content type string
429
+ */
430
+ private buildContentType(proofFormat: CredentialProofFormat | undefined): string {
336
431
  switch (proofFormat) {
337
432
  case 'jwt':
338
- return `application/statuslist+jwt`
433
+ return 'application/statuslist+jwt'
339
434
  case 'cbor':
340
- return `application/statuslist+cwt`
435
+ return 'application/statuslist+cwt'
436
+ case 'vc+jwt':
437
+ return 'application/statuslist+vc+jwt'
341
438
  case 'lds':
342
439
  return 'application/statuslist+ld+json'
343
440
  default:
@@ -1,4 +1,4 @@
1
- import type { IAgentContext, ICredentialPlugin } from '@veramo/core'
1
+ import type { IAgentContext } from '@veramo/core'
2
2
  import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
3
3
  import {
4
4
  BitstringStatus,
@@ -25,24 +25,28 @@ import {
25
25
  StatusPurpose2021,
26
26
  } from '@sphereon/ssi-types'
27
27
  import { IBitstringStatusListEntryEntity, IStatusListEntryEntity, StatusListEntity } from '@sphereon/ssi-sdk.data-store'
28
+ import { IVcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'
28
29
 
29
30
  export interface IStatusList {
30
31
  /**
31
32
  * Creates a new status list of the specific type
32
33
  */
33
- createNewStatusList(args: CreateStatusListArgs, context: IAgentContext<ICredentialPlugin & IIdentifierResolution>): Promise<StatusListResult>
34
+ createNewStatusList(args: CreateStatusListArgs, context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>): Promise<StatusListResult>
34
35
 
35
36
  /**
36
37
  * Updates a status at the given index in the status list
37
38
  */
38
- updateStatusListIndex(args: UpdateStatusListIndexArgs, context: IAgentContext<ICredentialPlugin & IIdentifierResolution>): Promise<StatusListResult>
39
+ updateStatusListIndex(
40
+ args: UpdateStatusListIndexArgs,
41
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
42
+ ): Promise<StatusListResult>
39
43
 
40
44
  /**
41
45
  * Updates a status list using a base64 encoded list of statuses
42
46
  */
43
47
  updateStatusListFromEncodedList(
44
48
  args: UpdateStatusListFromEncodedListArgs,
45
- context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
49
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
46
50
  ): Promise<StatusListResult>
47
51
 
48
52
  /**
@@ -1,4 +1,4 @@
1
- import type { IAgentContext, ICredentialPlugin, IKeyManager } from '@veramo/core'
1
+ import type { IAgentContext, IKeyManager } from '@veramo/core'
2
2
  import { type CompactJWT, type CredentialProofFormat, type CWT, StatusListType } from '@sphereon/ssi-types'
3
3
  import type {
4
4
  CheckStatusIndexArgs,
@@ -19,8 +19,9 @@ import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-res
19
19
  import { createSignedJwt, decodeStatusListJWT } from './encoding/jwt'
20
20
  import { createSignedCbor, decodeStatusListCWT } from './encoding/cbor'
21
21
  import { IBitstringStatusListEntryEntity, IStatusListEntryEntity, OAuthStatusListEntity, StatusListEntity } from '@sphereon/ssi-sdk.data-store'
22
+ import { IVcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'
22
23
 
23
- type IRequiredContext = IAgentContext<ICredentialPlugin & IJwtService & IIdentifierResolution & IKeyManager>
24
+ type IRequiredContext = IAgentContext<IVcdmCredentialPlugin & IJwtService & IIdentifierResolution & IKeyManager>
24
25
 
25
26
  export const DEFAULT_BITS_PER_STATUS = 1 // 1 bit is sufficient for 0x00 - "VALID" 0x01 - "INVALID" saving space in the process
26
27
  export const DEFAULT_LIST_LENGTH = 250000
@@ -227,7 +228,7 @@ export class OAuthStatusListImplementation implements IStatusList {
227
228
 
228
229
  private async createSignedStatusList(
229
230
  proofFormat: CredentialProofFormat,
230
- context: IAgentContext<ICredentialPlugin & IJwtService & IIdentifierResolution & IKeyManager>,
231
+ context: IAgentContext<IVcdmCredentialPlugin & IJwtService & IIdentifierResolution & IKeyManager>,
231
232
  statusList: StatusList,
232
233
  issuerString: string,
233
234
  id: string,
@@ -1,4 +1,4 @@
1
- import type { IAgentContext, ICredentialPlugin, ProofFormat as VeramoProofFormat } from '@veramo/core'
1
+ import type { IAgentContext, ProofFormat as VeramoProofFormat } from '@veramo/core'
2
2
  import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
3
3
  import {
4
4
  CredentialMapper,
@@ -22,6 +22,7 @@ import type {
22
22
  import { Status2021, StatusList2021EntryCredentialStatus } from '../types'
23
23
  import { assertValidProofType, getAssertedProperty, getAssertedValue, getAssertedValues } from '../utils'
24
24
  import { IBitstringStatusListEntryEntity, IStatusListEntryEntity, StatusList2021Entity, StatusListEntity } from '@sphereon/ssi-sdk.data-store'
25
+ import { IVcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'
25
26
 
26
27
  export const DEFAULT_LIST_LENGTH = 250000
27
28
  export const DEFAULT_PROOF_FORMAT = 'lds' as CredentialProofFormat
@@ -29,7 +30,7 @@ export const DEFAULT_PROOF_FORMAT = 'lds' as CredentialProofFormat
29
30
  export class StatusList2021Implementation implements IStatusList {
30
31
  async createNewStatusList(
31
32
  args: CreateStatusListArgs,
32
- context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
33
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
33
34
  ): Promise<StatusListResult> {
34
35
  const length = args?.length ?? DEFAULT_LIST_LENGTH
35
36
  const proofFormat: CredentialProofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT
@@ -71,7 +72,7 @@ export class StatusList2021Implementation implements IStatusList {
71
72
 
72
73
  async updateStatusListIndex(
73
74
  args: UpdateStatusListIndexArgs,
74
- context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
75
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
75
76
  ): Promise<StatusListResult> {
76
77
  const credential = args.statusListCredential
77
78
  const uniform = CredentialMapper.toUniformCredential(credential)
@@ -118,7 +119,7 @@ export class StatusList2021Implementation implements IStatusList {
118
119
 
119
120
  async updateStatusListFromEncodedList(
120
121
  args: UpdateStatusListFromEncodedListArgs,
121
- context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
122
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
122
123
  ): Promise<StatusListResult> {
123
124
  if (!args.statusList2021) {
124
125
  throw new Error('statusList2021 options required for type StatusList2021')
@@ -238,7 +239,7 @@ export class StatusList2021Implementation implements IStatusList {
238
239
  proofFormat: VeramoProofFormat
239
240
  keyRef?: string
240
241
  },
241
- context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
242
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
242
243
  ): Promise<StatusListCredential> {
243
244
  const identifier = await context.agent.identifierManagedGet({
244
245
  identifier: typeof args.issuer === 'string' ? args.issuer : args.issuer.id,