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

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.13+61bcf6d3",
4
+ "version": "0.34.1-feature.SSISDK.17.bitstring.sl.16+6964608d",
5
5
  "source": "src/index.ts",
6
6
  "type": "module",
7
7
  "main": "./dist/index.cjs",
@@ -31,9 +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.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",
34
+ "@sphereon/ssi-sdk.credential-vcdm": "0.34.1-feature.SSISDK.17.bitstring.sl.16+6964608d",
35
+ "@sphereon/ssi-sdk.data-store": "0.34.1-feature.SSISDK.17.bitstring.sl.16+6964608d",
36
+ "@sphereon/ssi-types": "0.34.1-feature.SSISDK.17.bitstring.sl.16+6964608d",
37
37
  "@sphereon/vc-status-list": "7.0.0-next.0",
38
38
  "@veramo/core": "4.2.0",
39
39
  "@veramo/credential-status": "4.2.0",
@@ -72,5 +72,5 @@
72
72
  "SSI",
73
73
  "StatusList2021"
74
74
  ],
75
- "gitHead": "61bcf6d37bcb3d77036b5415d72853c3ba3f9273"
75
+ "gitHead": "6964608dcd10f9cc0935ef31e7dec85fb4fe55fd"
76
76
  }
package/src/functions.ts CHANGED
@@ -1,24 +1,22 @@
1
1
  import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
2
- import {
3
- CredentialMapper,
4
- type CredentialProofFormat,
5
- type StatusListCredential,
6
- StatusListDriverType,
7
- StatusListType,
8
- type StatusPurpose2021,
9
- } from '@sphereon/ssi-types'
2
+ import { CredentialMapper, type CredentialProofFormat, type StatusListCredential, StatusListType, type StatusPurpose2021 } from '@sphereon/ssi-types'
10
3
  import type { CredentialStatus, DIDDocument, IAgentContext, ProofFormat as VeramoProofFormat } from '@veramo/core'
11
4
 
12
- import { IAddStatusListArgs, IBitstringStatusListEntryEntity, IStatusListEntryEntity, StatusListEntity } from '@sphereon/ssi-sdk.data-store'
5
+ import {
6
+ BitstringStatusListEntryCredentialStatus,
7
+ IBitstringStatusListEntryEntity,
8
+ IStatusListEntryEntity,
9
+ StatusListEntity,
10
+ } from '@sphereon/ssi-sdk.data-store'
13
11
 
14
12
  import { checkStatus } from '@sphereon/vc-status-list'
15
13
 
16
14
  // @ts-ignore
17
15
  import { CredentialJwtOrJSON, StatusMethod } from 'credential-status'
18
16
  import {
19
- BitstringStatus,
20
- BitstringStatusListEntryCredentialStatus,
21
17
  CreateNewStatusListFuncArgs,
18
+ IMergeDetailsWithEntityArgs,
19
+ IToDetailsFromCredentialArgs,
22
20
  Status2021,
23
21
  StatusList2021EntryCredentialStatus,
24
22
  StatusList2021ToVerifiableCredentialArgs,
@@ -31,7 +29,18 @@ import {
31
29
  import { assertValidProofType, determineStatusListType, getAssertedValue, getAssertedValues } from './utils'
32
30
  import { getStatusListImplementation } from './impl/StatusListFactory'
33
31
  import { IVcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'
32
+ import {
33
+ IBitstringStatusListImplementationResult,
34
+ IExtractedCredentialDetails,
35
+ IOAuthStatusListImplementationResult,
36
+ IStatusList2021ImplementationResult,
37
+ } from './impl/IStatusList'
34
38
 
39
+ /**
40
+ * Fetches a status list credential from a URL
41
+ * @param args - Object containing the status list credential URL
42
+ * @returns Promise resolving to the fetched StatusListCredential
43
+ */
35
44
  export async function fetchStatusListCredential(args: { statusListCredential: string }): Promise<StatusListCredential> {
36
45
  const url = getAssertedValue('statusListCredential', args.statusListCredential)
37
46
  try {
@@ -50,6 +59,11 @@ export async function fetchStatusListCredential(args: { statusListCredential: st
50
59
  }
51
60
  }
52
61
 
62
+ /**
63
+ * Creates a status checking function for credential-status plugin
64
+ * @param args - Configuration options for status verification
65
+ * @returns StatusMethod function for checking credential status
66
+ */
53
67
  export function statusPluginStatusFunction(args: {
54
68
  documentLoader: any
55
69
  suite: any
@@ -75,7 +89,8 @@ export function statusPluginStatusFunction(args: {
75
89
 
76
90
  /**
77
91
  * Function that can be used together with @digitalbazar/vc and @digitialcredentials/vc
78
- * @param args
92
+ * @param args - Configuration options for status verification
93
+ * @returns Function for checking credential status
79
94
  */
80
95
  export function vcLibCheckStatusFunction(args: {
81
96
  mandatoryCredentialStatus?: boolean
@@ -102,6 +117,11 @@ export function vcLibCheckStatusFunction(args: {
102
117
  }
103
118
  }
104
119
 
120
+ /**
121
+ * Checks the status of a credential using its credential status information
122
+ * @param args - Parameters for credential status verification
123
+ * @returns Promise resolving to verification result with error details if any
124
+ */
105
125
  export async function checkStatusForCredential(args: {
106
126
  credential: StatusListCredential
107
127
  documentLoader: any
@@ -142,13 +162,18 @@ export async function simpleCheckStatusFromStatusListUrl(args: {
142
162
  type?: StatusListType | 'StatusList2021Entry'
143
163
  id?: string
144
164
  statusListIndex: string
145
- }): Promise<number | Status2021 | StatusOAuth | BitstringStatus> {
165
+ }): Promise<number | Status2021 | StatusOAuth> {
146
166
  return checkStatusIndexFromStatusListCredential({
147
167
  ...args,
148
168
  statusListCredential: await fetchStatusListCredential(args),
149
169
  })
150
170
  }
151
171
 
172
+ /**
173
+ * Checks the status at a specific index in a status list credential
174
+ * @param args - Parameters including credential and index to check
175
+ * @returns Promise resolving to status value at the specified index
176
+ */
152
177
  export async function checkStatusIndexFromStatusListCredential(args: {
153
178
  statusListCredential: StatusListCredential
154
179
  statusPurpose?: StatusPurpose2021 | string | string[]
@@ -156,7 +181,7 @@ export async function checkStatusIndexFromStatusListCredential(args: {
156
181
  id?: string
157
182
  statusListIndex: string | number
158
183
  bitsPerStatus?: number
159
- }): Promise<number | Status2021 | StatusOAuth | BitstringStatus> {
184
+ }): Promise<number | Status2021 | StatusOAuth> {
160
185
  const statusListType: StatusListType = determineStatusListType(args.statusListCredential)
161
186
  const implementation = getStatusListImplementation(statusListType)
162
187
  return implementation.checkStatusIndex(args)
@@ -171,6 +196,12 @@ export async function createNewStatusList(
171
196
  return implementation.createNewStatusList(args, context)
172
197
  }
173
198
 
199
+ /**
200
+ * Updates a status index in a status list credential
201
+ * @param args - Parameters for status update including credential and new value
202
+ * @param context - Agent context with required plugins
203
+ * @returns Promise resolving to updated status list details
204
+ */
174
205
  export async function updateStatusIndexFromStatusListCredential(
175
206
  args: UpdateStatusListIndexArgs,
176
207
  context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
@@ -181,33 +212,54 @@ export async function updateStatusIndexFromStatusListCredential(
181
212
  return implementation.updateStatusListIndex(args, context)
182
213
  }
183
214
 
184
- export async function statusListCredentialToDetails({
185
- statusListType,
186
- correlationId,
187
- driverType,
188
- statusListCredential,
189
- bitsPerStatus,
190
- }: {
191
- statusListType: StatusListType
192
- statusListCredential: StatusListCredential
193
- correlationId?: string
194
- driverType?: StatusListDriverType
195
- bitsPerStatus?: number
196
- }): Promise<StatusListResult & Partial<IAddStatusListArgs>> {
197
- const credential = getAssertedValue('statusListCredential', statusListCredential)
215
+ /**
216
+ * Extracts credential details from a status list credential
217
+ * @param statusListCredential - The status list credential to extract from
218
+ * @returns Promise resolving to extracted credential details
219
+ */
220
+ export async function extractCredentialDetails(statusListCredential: StatusListCredential): Promise<IExtractedCredentialDetails> {
221
+ const statusListType = determineStatusListType(statusListCredential)
198
222
  const implementation = getStatusListImplementation(statusListType)
223
+ return implementation.extractCredentialDetails(statusListCredential)
224
+ }
199
225
 
200
- // The implementation should now return all the type-specific fields needed for the entity
201
- const result = await implementation.toStatusListDetails({
202
- statusListPayload: credential,
203
- correlationId: correlationId,
204
- driverType: driverType,
205
- bitsPerStatus: bitsPerStatus,
206
- })
226
+ export async function toStatusListDetails(
227
+ args: IToDetailsFromCredentialArgs,
228
+ ): Promise<StatusListResult & (IStatusList2021ImplementationResult | IOAuthStatusListImplementationResult | IBitstringStatusListImplementationResult)>
229
+
230
+ export async function toStatusListDetails(
231
+ args: IMergeDetailsWithEntityArgs,
232
+ ): Promise<StatusListResult & (IStatusList2021ImplementationResult | IOAuthStatusListImplementationResult | IBitstringStatusListImplementationResult)>
207
233
 
208
- return result
234
+ /**
235
+ * Converts credential and metadata into detailed status list information
236
+ * Handles both CREATE/READ and UPDATE contexts based on input arguments
237
+ * @param args - Either credential-based args or entity-based args for merging
238
+ * @returns Promise resolving to complete status list details
239
+ */
240
+ export async function toStatusListDetails(
241
+ args: IToDetailsFromCredentialArgs | IMergeDetailsWithEntityArgs,
242
+ ): Promise<
243
+ StatusListResult & (IStatusList2021ImplementationResult | IOAuthStatusListImplementationResult | IBitstringStatusListImplementationResult)
244
+ > {
245
+ if ('statusListCredential' in args) {
246
+ // CREATE/READ context
247
+ const statusListType = args.statusListType
248
+ const implementation = getStatusListImplementation(statusListType)
249
+ return implementation.toStatusListDetails(args)
250
+ } else {
251
+ // UPDATE context
252
+ const statusListType = args.statusListEntity.type
253
+ const implementation = getStatusListImplementation(statusListType)
254
+ return implementation.toStatusListDetails(args)
255
+ }
209
256
  }
210
257
 
258
+ /**
259
+ * Creates a credential status object from status list and entry information
260
+ * @param args - Parameters including status list, entry, and index
261
+ * @returns Promise resolving to appropriate credential status type
262
+ */
211
263
  export async function createCredentialStatusFromStatusList(args: {
212
264
  statusList: StatusListEntity
213
265
  statusListEntry: IStatusListEntryEntity | IBitstringStatusListEntryEntity
@@ -227,6 +279,12 @@ export async function createCredentialStatusFromStatusList(args: {
227
279
  })
228
280
  }
229
281
 
282
+ /**
283
+ * Updates a status list using a base64 encoded list of statuses
284
+ * @param args - Parameters including encoded list and update details
285
+ * @param context - Agent context with required plugins
286
+ * @returns Promise resolving to updated status list details
287
+ */
230
288
  export async function updateStatusListIndexFromEncodedList(
231
289
  args: UpdateStatusListFromEncodedListArgs,
232
290
  context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
@@ -236,6 +294,12 @@ export async function updateStatusListIndexFromEncodedList(
236
294
  return implementation.updateStatusListFromEncodedList(args, context)
237
295
  }
238
296
 
297
+ /**
298
+ * Converts a StatusList2021 to a verifiable credential
299
+ * @param args - Parameters for credential creation including issuer and encoded list
300
+ * @param context - Agent context with required plugins
301
+ * @returns Promise resolving to signed status list credential
302
+ */
239
303
  export async function statusList2021ToVerifiableCredential(
240
304
  args: StatusList2021ToVerifiableCredentialArgs,
241
305
  context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
@@ -28,14 +28,13 @@ import {
28
28
  StatusListType,
29
29
  } from '@sphereon/ssi-types'
30
30
 
31
- import type { IBitstringStatusListImplementationResult, IStatusList } from './IStatusList'
31
+ import type { IBitstringStatusListImplementationResult, IExtractedCredentialDetails, IStatusList } from './IStatusList'
32
32
  import {
33
- BitstringStatus,
34
- BitstringStatusListEntryCredentialStatus,
35
33
  CheckStatusIndexArgs,
36
34
  CreateStatusListArgs,
35
+ IMergeDetailsWithEntityArgs,
36
+ IToDetailsFromCredentialArgs,
37
37
  StatusListResult,
38
- ToStatusListDetailsArgs,
39
38
  UpdateStatusListFromEncodedListArgs,
40
39
  UpdateStatusListIndexArgs,
41
40
  } from '../types'
@@ -48,11 +47,17 @@ import {
48
47
  BitstringStatusPurpose,
49
48
  createStatusListCredential,
50
49
  } from '@4sure-tech/vc-bitstring-status-lists'
51
- import { BitstringStatusListEntity, IBitstringStatusListEntryEntity, IStatusListEntryEntity, StatusListEntity } from '@sphereon/ssi-sdk.data-store'
50
+ import {
51
+ BitstringStatusListEntity,
52
+ BitstringStatusListEntryCredentialStatus,
53
+ IBitstringStatusListEntryEntity,
54
+ IStatusListEntryEntity,
55
+ StatusListEntity,
56
+ } from '@sphereon/ssi-sdk.data-store'
52
57
  import { IVcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'
53
58
 
54
59
  export const DEFAULT_LIST_LENGTH = 131072 // W3C spec minimum
55
- export const DEFAULT_PROOF_FORMAT = 'lds' as CredentialProofFormat
60
+ export const DEFAULT_PROOF_FORMAT = 'vc+jwt' as CredentialProofFormat
56
61
  export const DEFAULT_STATUS_PURPOSE: BitstringStatusPurpose = 'revocation'
57
62
 
58
63
  /**
@@ -148,9 +153,10 @@ export class BitstringStatusListImplementation implements IStatusList {
148
153
 
149
154
  const index = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
150
155
  const statusList: BitstreamStatusList = await BitstreamStatusList.decode({ encodedList: origEncodedList, statusSize: args.bitsPerStatus })
151
- statusList.setStatus(index, args.value)
156
+ const bitstringStatusId = args.value as number
157
+ statusList.setStatus(index, bitstringStatusId)
152
158
 
153
- const proofFormat = CredentialMapper.detectDocumentType(credential) === DocumentFormat.JWT ? 'jwt' : 'lds'
159
+ const proofFormat = CredentialMapper.detectDocumentType(credential) === DocumentFormat.JWT ? 'vc+jwt' : 'lds'
154
160
 
155
161
  const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject
156
162
 
@@ -275,7 +281,7 @@ export class BitstringStatusListImplementation implements IStatusList {
275
281
  * @param args - Check parameters including the status list credential and index
276
282
  * @returns Promise resolving to the status value at the specified index
277
283
  */
278
- async checkStatusIndex(args: CheckStatusIndexArgs): Promise<BitstringStatus> {
284
+ async checkStatusIndex(args: CheckStatusIndexArgs): Promise<number> {
279
285
  if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
280
286
  return Promise.reject(Error('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (checkStatusIndex)'))
281
287
  }
@@ -293,61 +299,115 @@ export class BitstringStatusListImplementation implements IStatusList {
293
299
  }
294
300
 
295
301
  /**
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
302
+ * Performs the initial parsing of a StatusListCredential.
303
+ * This method handles expensive operations like JWT/CWT decoding once.
304
+ * It extracts all details available from the credential payload itself.
300
305
  */
301
- async toStatusListDetails(args: ToStatusListDetailsArgs): Promise<StatusListResult & IBitstringStatusListImplementationResult> {
302
- const { statusListPayload, bitsPerStatus } = args
303
- if (!bitsPerStatus || bitsPerStatus < 1) {
304
- return Promise.reject(Error('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (toStatusListDetails)'))
305
- }
306
-
307
- const uniform = CredentialMapper.toUniformCredential(statusListPayload)
306
+ async extractCredentialDetails(credential: StatusListCredential): Promise<IExtractedCredentialDetails> {
307
+ const uniform = CredentialMapper.toUniformCredential(credential)
308
308
  const { issuer, credentialSubject } = uniform
309
- const id = getAssertedValue('id', uniform.id)
310
- const encodedList = getAssertedProperty('encodedList', credentialSubject)
311
- const proofFormat: CredentialProofFormat = CredentialMapper.detectDocumentType(statusListPayload) === DocumentFormat.JWT ? 'vc+jwt' : 'lds'
312
- const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject
313
- const statusPurpose = getAssertedProperty('statusPurpose', credSubject)
314
- const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : undefined
315
- const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : undefined
316
- const ttl = credSubject.ttl
317
- const statuslistLength: number = BitstreamStatusList.getStatusListLength(encodedList, bitsPerStatus)
309
+ const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject
318
310
 
319
311
  return {
320
- // Base implementation fields
321
- id,
322
- encodedList,
312
+ id: getAssertedValue('id', uniform.id),
323
313
  issuer,
324
- type: StatusListType.BitstringStatusList,
325
- proofFormat,
326
- length: statuslistLength,
327
- statusListCredential: statusListPayload,
328
- statuslistContentType: this.buildContentType(proofFormat),
329
- correlationId: args.correlationId, // FIXME these do not need to be inside the impl
330
- driverType: args.driverType, // FIXME these do not need to be inside the impl
331
-
332
- // Flattened Bitstring-specific fields
333
- statusPurpose,
334
- bitsPerStatus,
335
- ...(validFrom && { validFrom }),
336
- ...(validUntil && { validUntil }),
337
- ...(ttl && { ttl }),
314
+ encodedList: getAssertedProperty('encodedList', subject),
315
+ }
316
+ }
338
317
 
339
- // Legacy nested structure for backward compatibility
340
- bitstringStatusList: {
318
+ /**
319
+ * Converts a status list credential payload to detailed status list information
320
+ *
321
+ * @param args - Conversion parameters including the status list payload
322
+ * @returns Promise resolving to detailed status list information
323
+ */
324
+ // For CREATE and READ contexts
325
+ async toStatusListDetails(args: IToDetailsFromCredentialArgs): Promise<StatusListResult & IBitstringStatusListImplementationResult>
326
+ // For UPDATE contexts
327
+ async toStatusListDetails(args: IMergeDetailsWithEntityArgs): Promise<StatusListResult & IBitstringStatusListImplementationResult>
328
+ async toStatusListDetails(
329
+ args: IToDetailsFromCredentialArgs | IMergeDetailsWithEntityArgs,
330
+ ): Promise<StatusListResult & IBitstringStatusListImplementationResult> {
331
+ if ('statusListCredential' in args) {
332
+ // CREATE/READ context
333
+ const { statusListCredential, bitsPerStatus, correlationId, driverType } = args
334
+ if (!bitsPerStatus || bitsPerStatus < 1) {
335
+ return Promise.reject(Error('bitsPerStatus must be set for bitstring status lists and must be 1 or higher'))
336
+ }
337
+
338
+ const uniform = CredentialMapper.toUniformCredential(statusListCredential)
339
+ const { issuer, credentialSubject } = uniform
340
+ const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject
341
+
342
+ const id = getAssertedValue('id', uniform.id)
343
+ const encodedList = getAssertedProperty('encodedList', subject)
344
+ const statusPurpose = getAssertedProperty('statusPurpose', subject)
345
+ const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : undefined
346
+ const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : undefined
347
+ const ttl = subject.ttl
348
+ const proofFormat: CredentialProofFormat = CredentialMapper.detectDocumentType(statusListCredential) === DocumentFormat.JWT ? 'vc+jwt' : 'lds'
349
+ const statuslistLength = BitstreamStatusList.getStatusListLength(encodedList, bitsPerStatus)
350
+
351
+ return {
352
+ id,
353
+ encodedList,
354
+ issuer,
355
+ type: StatusListType.BitstringStatusList,
356
+ proofFormat,
357
+ length: statuslistLength,
358
+ statusListCredential,
359
+ statuslistContentType: this.buildContentType(proofFormat),
360
+ correlationId,
361
+ driverType,
341
362
  statusPurpose,
342
363
  bitsPerStatus,
343
364
  ...(validFrom && { validFrom }),
344
365
  ...(validUntil && { validUntil }),
345
366
  ...(ttl && { ttl }),
346
- },
347
-
348
- // Optional fields from args
349
- ...(args.correlationId && { correlationId: args.correlationId }),
350
- ...(args.driverType && { driverType: args.driverType }),
367
+ bitstringStatusList: {
368
+ statusPurpose,
369
+ bitsPerStatus,
370
+ ...(validFrom && { validFrom }),
371
+ ...(validUntil && { validUntil }),
372
+ ...(ttl && { ttl }),
373
+ },
374
+ }
375
+ } else {
376
+ // UPDATE context
377
+ const { extractedDetails, statusListEntity } = args
378
+ const bitstringEntity = statusListEntity as BitstringStatusListEntity
379
+ if (!bitstringEntity.bitsPerStatus) {
380
+ return Promise.reject(Error('bitsPerStatus must be present for a bitstring status list'))
381
+ }
382
+
383
+ const proofFormat: CredentialProofFormat =
384
+ CredentialMapper.detectDocumentType(statusListEntity.statusListCredential!) === DocumentFormat.JWT ? 'vc+jwt' : 'lds'
385
+ const statuslistLength = BitstreamStatusList.getStatusListLength(extractedDetails.encodedList, bitstringEntity.bitsPerStatus)
386
+
387
+ return {
388
+ id: extractedDetails.id,
389
+ encodedList: extractedDetails.encodedList,
390
+ issuer: extractedDetails.issuer,
391
+ type: StatusListType.BitstringStatusList,
392
+ proofFormat,
393
+ length: statuslistLength,
394
+ statusListCredential: statusListEntity.statusListCredential!,
395
+ statuslistContentType: this.buildContentType(proofFormat),
396
+ correlationId: statusListEntity.correlationId,
397
+ driverType: statusListEntity.driverType,
398
+ statusPurpose: bitstringEntity.statusPurpose,
399
+ bitsPerStatus: bitstringEntity.bitsPerStatus,
400
+ ...(bitstringEntity.validFrom && { validFrom: bitstringEntity.validFrom }),
401
+ ...(bitstringEntity.validUntil && { validUntil: bitstringEntity.validUntil }),
402
+ ...(bitstringEntity.ttl && { ttl: bitstringEntity.ttl }),
403
+ bitstringStatusList: {
404
+ statusPurpose: bitstringEntity.statusPurpose,
405
+ bitsPerStatus: bitstringEntity.bitsPerStatus,
406
+ ...(bitstringEntity.validFrom && { validFrom: bitstringEntity.validFrom }),
407
+ ...(bitstringEntity.validUntil && { validUntil: bitstringEntity.validUntil }),
408
+ ...(bitstringEntity.ttl && { ttl: bitstringEntity.ttl }),
409
+ },
410
+ }
351
411
  }
352
412
  }
353
413
 
@@ -364,25 +424,17 @@ export class BitstringStatusListImplementation implements IStatusList {
364
424
  }): Promise<BitstringStatusListEntryCredentialStatus> {
365
425
  const { statusList, statusListEntry, statusListIndex } = args
366
426
 
367
- // Type guard to ensure we have a bitstring entry
368
- const isBitstringEntry = (entry: IStatusListEntryEntity | IBitstringStatusListEntryEntity): entry is IBitstringStatusListEntryEntity => {
369
- return 'statusPurpose' in entry
370
- }
371
-
372
- if (!isBitstringEntry(statusListEntry)) {
373
- throw new Error('Expected bitstring status list entry for bitstring status list')
374
- }
375
-
376
- // Cast to BitstringStatusListEntity to access specific properties
377
427
  const bitstringStatusList = statusList as BitstringStatusListEntity
378
-
428
+ const bitstringStatusListEntry = statusListEntry as IBitstringStatusListEntryEntity
379
429
  return {
380
430
  id: `${statusList.id}#${statusListIndex}`,
381
431
  type: 'BitstringStatusListEntry',
382
- statusPurpose: statusListEntry.statusPurpose,
432
+ statusPurpose: bitstringStatusListEntry.statusPurpose,
383
433
  statusListIndex: '' + statusListIndex,
384
434
  statusListCredential: statusList.id,
385
435
  bitsPerStatus: bitstringStatusList.bitsPerStatus,
436
+ statusMessage: bitstringStatusListEntry.statusMessage,
437
+ statusReference: bitstringStatusListEntry.statusReference,
386
438
  } satisfies BitstringStatusListEntryCredentialStatus
387
439
  }
388
440
 
@@ -1,16 +1,15 @@
1
1
  import type { IAgentContext } from '@veramo/core'
2
2
  import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
3
3
  import {
4
- BitstringStatus,
5
- BitstringStatusListEntryCredentialStatus,
6
4
  CheckStatusIndexArgs,
7
5
  CreateStatusListArgs,
6
+ IMergeDetailsWithEntityArgs,
7
+ IToDetailsFromCredentialArgs,
8
8
  Status2021,
9
9
  StatusList2021EntryCredentialStatus,
10
10
  StatusListOAuthEntryCredentialStatus,
11
11
  StatusListResult,
12
12
  StatusOAuth,
13
- ToStatusListDetailsArgs,
14
13
  UpdateStatusListFromEncodedListArgs,
15
14
  UpdateStatusListIndexArgs,
16
15
  } from '../types'
@@ -24,8 +23,21 @@ import {
24
23
  StatusListType,
25
24
  StatusPurpose2021,
26
25
  } from '@sphereon/ssi-types'
27
- import { IBitstringStatusListEntryEntity, IStatusListEntryEntity, StatusListEntity } from '@sphereon/ssi-sdk.data-store'
26
+ import {
27
+ BitstringStatusListEntryCredentialStatus,
28
+ IBitstringStatusListEntryEntity,
29
+ IStatusListEntryEntity,
30
+ StatusListEntity,
31
+ } from '@sphereon/ssi-sdk.data-store'
28
32
  import { IVcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'
33
+ import { DecodedStatusListPayload } from './encoding/common'
34
+
35
+ export interface IExtractedCredentialDetails {
36
+ id: string
37
+ issuer: string | IIssuer
38
+ encodedList: string
39
+ decodedPayload?: DecodedStatusListPayload
40
+ }
29
41
 
30
42
  export interface IStatusList {
31
43
  /**
@@ -52,13 +64,29 @@ export interface IStatusList {
52
64
  /**
53
65
  * Checks the status at a given index in the status list
54
66
  */
55
- checkStatusIndex(args: CheckStatusIndexArgs): Promise<number | Status2021 | StatusOAuth | BitstringStatus>
67
+ checkStatusIndex(args: CheckStatusIndexArgs): Promise<number | Status2021 | StatusOAuth>
68
+
69
+ /**
70
+ * Performs the initial parsing of a StatusListCredential.
71
+ * This method handles expensive operations like JWT/CWT decoding once.
72
+ * It extracts all details available from the credential payload itself.
73
+ */
74
+ extractCredentialDetails(credential: StatusListCredential): Promise<IExtractedCredentialDetails>
75
+
76
+ /**
77
+ * Converts a credential and its known metadata into a full StatusListResult.
78
+ */
79
+ toStatusListDetails(
80
+ args: IToDetailsFromCredentialArgs,
81
+ ): Promise<
82
+ StatusListResult & (IStatusList2021ImplementationResult | IOAuthStatusListImplementationResult | IBitstringStatusListImplementationResult)
83
+ >
56
84
 
57
85
  /**
58
- * Collects the status list details - returns flattened entity data ready for storage
86
+ * Merges pre-parsed details from a new credential with an existing database entity.
59
87
  */
60
88
  toStatusListDetails(
61
- args: ToStatusListDetailsArgs,
89
+ args: IMergeDetailsWithEntityArgs,
62
90
  ): Promise<
63
91
  StatusListResult & (IStatusList2021ImplementationResult | IOAuthStatusListImplementationResult | IBitstringStatusListImplementationResult)
64
92
  >