@sphereon/ssi-sdk.vc-status-list 0.34.1-next.3 → 0.34.1-next.40

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.
@@ -0,0 +1,496 @@
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'
20
+ import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
21
+
22
+ import {
23
+ CredentialMapper,
24
+ type CredentialProofFormat,
25
+ DocumentFormat,
26
+ type IIssuer,
27
+ type StatusListCredential,
28
+ StatusListType,
29
+ } from '@sphereon/ssi-types'
30
+
31
+ import type { IBitstringStatusListImplementationResult, IExtractedCredentialDetails, IStatusList } from './IStatusList'
32
+ import {
33
+ CheckStatusIndexArgs,
34
+ CreateStatusListArgs,
35
+ IMergeDetailsWithEntityArgs,
36
+ IToDetailsFromCredentialArgs,
37
+ StatusListResult,
38
+ UpdateStatusListFromEncodedListArgs,
39
+ UpdateStatusListIndexArgs,
40
+ } from '../types'
41
+
42
+ import { assertValidProofType, ensureDate, getAssertedProperty, getAssertedValue, getAssertedValues } from '../utils'
43
+ import { BitstringStatusListCredential } from '../types/BitstringStatusList'
44
+ import {
45
+ BitstreamStatusList,
46
+ BitstringStatusListCredentialUnsigned,
47
+ BitstringStatusPurpose,
48
+ createStatusListCredential,
49
+ } from '@4sure-tech/vc-bitstring-status-lists'
50
+ import {
51
+ BitstringStatusListEntity,
52
+ BitstringStatusListEntryCredentialStatus,
53
+ IBitstringStatusListEntryEntity,
54
+ IStatusListEntryEntity,
55
+ StatusListEntity,
56
+ } from '@sphereon/ssi-sdk.data-store'
57
+ import { IVcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'
58
+
59
+ export const DEFAULT_LIST_LENGTH = 131072 // W3C spec minimum
60
+ export const DEFAULT_PROOF_FORMAT = 'vc+jwt' as CredentialProofFormat
61
+ export const DEFAULT_STATUS_PURPOSE: BitstringStatusPurpose = 'revocation'
62
+
63
+ /**
64
+ * Implementation of the IStatusList interface for W3C Bitstring Status Lists
65
+ *
66
+ * This class handles the creation, updating, and verification of bitstring status lists
67
+ * according to the W3C Bitstring Status List specification. It supports multiple
68
+ * status purposes (revocation, suspension, etc.) and various proof formats.
69
+ */
70
+ export class BitstringStatusListImplementation implements IStatusList {
71
+ /**
72
+ * Creates a new bitstring status list with the specified configuration
73
+ *
74
+ * @param args - Configuration for the new status list including issuer, purpose, and size
75
+ * @param context - Veramo agent context for credential operations
76
+ * @returns Promise resolving to the created status list details
77
+ */
78
+ async createNewStatusList(
79
+ args: CreateStatusListArgs,
80
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
81
+ ): Promise<StatusListResult> {
82
+ if (!args.bitstringStatusList) {
83
+ throw new Error('BitstringStatusList options are required for type BitstringStatusList')
84
+ }
85
+
86
+ const length = args?.length ?? DEFAULT_LIST_LENGTH
87
+ const proofFormat: CredentialProofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT
88
+ assertValidProofType(StatusListType.BitstringStatusList, proofFormat)
89
+
90
+ const { issuer, id } = args
91
+ const correlationId = getAssertedValue('correlationId', args.correlationId)
92
+ const { statusPurpose, bitsPerStatus, validFrom, validUntil, ttl } = args.bitstringStatusList
93
+
94
+ const unsignedCredential: BitstringStatusListCredentialUnsigned = await createStatusListCredential({
95
+ id,
96
+ issuer,
97
+ statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
98
+ validFrom: ensureDate(validFrom),
99
+ validUntil: ensureDate(validUntil),
100
+ ttl,
101
+ })
102
+ const statusListCredential = await this.createVerifiableCredential(
103
+ {
104
+ unsignedCredential,
105
+ id,
106
+ issuer,
107
+ proofFormat,
108
+ keyRef: args.keyRef,
109
+ },
110
+ context,
111
+ )
112
+
113
+ return {
114
+ encodedList: unsignedCredential.credentialSubject.encodedList,
115
+ statusListCredential,
116
+ bitstringStatusList: {
117
+ statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
118
+ ...(unsignedCredential.validFrom && { validFrom: new Date(unsignedCredential.validFrom) }),
119
+ ...(unsignedCredential.validUntil && { validUntil: new Date(unsignedCredential.validUntil) }),
120
+ ttl,
121
+ bitsPerStatus,
122
+ },
123
+ length,
124
+ type: StatusListType.BitstringStatusList,
125
+ proofFormat,
126
+ id,
127
+ correlationId,
128
+ issuer,
129
+ statuslistContentType: this.buildContentType(proofFormat),
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Updates the status of a specific credential in an existing status list
135
+ *
136
+ * @param args - Update parameters including the status list credential, index, and new value
137
+ * @param context - Veramo agent context for credential operations
138
+ * @returns Promise resolving to the updated status list details
139
+ */
140
+ async updateStatusListIndex(
141
+ args: UpdateStatusListIndexArgs,
142
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
143
+ ): Promise<StatusListResult> {
144
+ if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
145
+ return Promise.reject(Error('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListIndex)'))
146
+ }
147
+
148
+ const credential = args.statusListCredential
149
+ const uniform = CredentialMapper.toUniformCredential(credential)
150
+ const { issuer, credentialSubject } = uniform
151
+ const id = getAssertedValue('id', uniform.id)
152
+ const origEncodedList = getAssertedProperty('encodedList', credentialSubject)
153
+
154
+ const index = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
155
+ const statusList: BitstreamStatusList = await BitstreamStatusList.decode({ encodedList: origEncodedList, statusSize: args.bitsPerStatus })
156
+ const bitstringStatusId = args.value as number
157
+ statusList.setStatus(index, bitstringStatusId)
158
+
159
+ const proofFormat = CredentialMapper.detectDocumentType(credential) === DocumentFormat.JWT ? 'vc+jwt' : 'lds'
160
+
161
+ const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject
162
+
163
+ const statusPurpose = getAssertedProperty('statusPurpose', credSubject)
164
+
165
+ const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : undefined
166
+ const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : undefined
167
+ const ttl = credSubject.ttl
168
+
169
+ const unsignedCredential: BitstringStatusListCredentialUnsigned = await createStatusListCredential({
170
+ id,
171
+ issuer,
172
+ statusList,
173
+ statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
174
+ validFrom: ensureDate(validFrom),
175
+ validUntil: ensureDate(validUntil),
176
+ ttl,
177
+ })
178
+
179
+ const updatedCredential = await this.createVerifiableCredential(
180
+ {
181
+ unsignedCredential,
182
+ id,
183
+ issuer,
184
+ proofFormat,
185
+ keyRef: args.keyRef,
186
+ },
187
+ context,
188
+ )
189
+
190
+ return {
191
+ statusListCredential: updatedCredential,
192
+ encodedList: unsignedCredential.credentialSubject.encodedList,
193
+ bitstringStatusList: {
194
+ statusPurpose,
195
+ ...(unsignedCredential.validFrom && { validFrom: new Date(unsignedCredential.validFrom) }),
196
+ ...(unsignedCredential.validUntil && { validUntil: new Date(unsignedCredential.validUntil) }),
197
+ bitsPerStatus: args.bitsPerStatus,
198
+ ttl,
199
+ },
200
+ length: statusList.getLength(),
201
+ type: StatusListType.BitstringStatusList,
202
+ proofFormat,
203
+ id,
204
+ issuer,
205
+ statuslistContentType: this.buildContentType(proofFormat),
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Updates a status list by decoding an encoded list, modifying it, and re-encoding
211
+ *
212
+ * @param args - Update parameters including encoded list, index, and new value
213
+ * @param context - Veramo agent context for credential operations
214
+ * @returns Promise resolving to the updated status list details
215
+ */
216
+ async updateStatusListFromEncodedList(
217
+ args: UpdateStatusListFromEncodedListArgs,
218
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
219
+ ): Promise<StatusListResult> {
220
+ if (!args.bitstringStatusList) {
221
+ throw new Error('bitstringStatusList options required for type BitstringStatusList')
222
+ }
223
+
224
+ if (args.bitstringStatusList.bitsPerStatus < 1) {
225
+ return Promise.reject(Error('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListFromEncodedList)'))
226
+ }
227
+
228
+ const { statusPurpose, bitsPerStatus, ttl, validFrom, validUntil } = args.bitstringStatusList
229
+
230
+ const proofFormat: CredentialProofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT
231
+ assertValidProofType(StatusListType.BitstringStatusList, proofFormat)
232
+
233
+ const { issuer, id } = getAssertedValues(args)
234
+ const statusList: BitstreamStatusList = await BitstreamStatusList.decode({ encodedList: args.encodedList, statusSize: bitsPerStatus })
235
+ const index = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
236
+ statusList.setStatus(index, args.value)
237
+
238
+ const unsignedCredential: BitstringStatusListCredentialUnsigned = await createStatusListCredential({
239
+ id,
240
+ issuer,
241
+ statusList,
242
+ statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
243
+ validFrom: ensureDate(validFrom),
244
+ validUntil: ensureDate(validUntil),
245
+ ttl,
246
+ })
247
+
248
+ const credential = await this.createVerifiableCredential(
249
+ {
250
+ unsignedCredential,
251
+ id,
252
+ issuer,
253
+ proofFormat,
254
+ keyRef: args.keyRef,
255
+ },
256
+ context,
257
+ )
258
+
259
+ return {
260
+ type: StatusListType.BitstringStatusList,
261
+ statusListCredential: credential,
262
+ encodedList: unsignedCredential.credentialSubject.encodedList,
263
+ bitstringStatusList: {
264
+ statusPurpose,
265
+ bitsPerStatus,
266
+ ...(unsignedCredential.validFrom && { validFrom: new Date(unsignedCredential.validFrom) }),
267
+ ...(unsignedCredential.validUntil && { validUntil: new Date(unsignedCredential.validUntil) }),
268
+ ttl,
269
+ },
270
+ length: statusList.getLength(),
271
+ proofFormat: args.proofFormat ?? 'lds',
272
+ id,
273
+ issuer,
274
+ statuslistContentType: this.buildContentType(proofFormat),
275
+ }
276
+ }
277
+
278
+ /**
279
+ * Checks the status of a specific credential by its index in the status list
280
+ *
281
+ * @param args - Check parameters including the status list credential and index
282
+ * @returns Promise resolving to the status value at the specified index
283
+ */
284
+ async checkStatusIndex(args: CheckStatusIndexArgs): Promise<number> {
285
+ if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
286
+ return Promise.reject(Error('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (checkStatusIndex)'))
287
+ }
288
+
289
+ const uniform = CredentialMapper.toUniformCredential(args.statusListCredential)
290
+ const { credentialSubject } = uniform
291
+ const encodedList = getAssertedProperty('encodedList', credentialSubject)
292
+
293
+ const statusList = await BitstreamStatusList.decode({ encodedList, statusSize: args.bitsPerStatus })
294
+ const numIndex = typeof args.statusListIndex === 'number' ? args.statusListIndex : parseInt(args.statusListIndex)
295
+ if (statusList.getLength() <= numIndex) {
296
+ throw new Error(`Status list index out of bounds, has ${statusList.getLength()} entries, requested ${numIndex}`)
297
+ }
298
+ return statusList.getStatus(numIndex)
299
+ }
300
+
301
+ /**
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.
305
+ */
306
+ async extractCredentialDetails(credential: StatusListCredential): Promise<IExtractedCredentialDetails> {
307
+ const uniform = CredentialMapper.toUniformCredential(credential)
308
+ const { issuer, credentialSubject } = uniform
309
+ const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject
310
+
311
+ return {
312
+ id: getAssertedValue('id', uniform.id),
313
+ issuer,
314
+ encodedList: getAssertedProperty('encodedList', subject),
315
+ }
316
+ }
317
+
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,
362
+ statusPurpose,
363
+ bitsPerStatus,
364
+ ...(validFrom && { validFrom }),
365
+ ...(validUntil && { validUntil }),
366
+ ...(ttl && { ttl }),
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
+ }
411
+ }
412
+ }
413
+
414
+ /**
415
+ * Creates a credential status entry for a specific credential in a status list
416
+ *
417
+ * @param args - Parameters including the status list, entry details, and index
418
+ * @returns Promise resolving to the credential status entry
419
+ */
420
+ async createCredentialStatus(args: {
421
+ statusList: StatusListEntity
422
+ statusListEntry: IStatusListEntryEntity | IBitstringStatusListEntryEntity
423
+ statusListIndex: number
424
+ }): Promise<BitstringStatusListEntryCredentialStatus> {
425
+ const { statusList, statusListEntry, statusListIndex } = args
426
+
427
+ const bitstringStatusList = statusList as BitstringStatusListEntity
428
+ const bitstringStatusListEntry = statusListEntry as IBitstringStatusListEntryEntity
429
+ return {
430
+ id: `${statusList.id}#${statusListIndex}`,
431
+ type: 'BitstringStatusListEntry',
432
+ statusPurpose: bitstringStatusListEntry.statusPurpose,
433
+ statusListIndex: '' + statusListIndex,
434
+ statusListCredential: statusList.id,
435
+ bitsPerStatus: bitstringStatusList.bitsPerStatus,
436
+ statusMessage: bitstringStatusListEntry.statusMessage,
437
+ statusReference: bitstringStatusListEntry.statusReference,
438
+ } satisfies BitstringStatusListEntryCredentialStatus
439
+ }
440
+
441
+ /**
442
+ * Creates a signed verifiable credential from an unsigned status list credential
443
+ *
444
+ * @param args - Parameters including the unsigned credential and signing details
445
+ * @param context - Veramo agent context for credential operations
446
+ * @returns Promise resolving to the signed credential
447
+ */
448
+ private async createVerifiableCredential(
449
+ args: {
450
+ unsignedCredential: BitstringStatusListCredentialUnsigned
451
+ id: string
452
+ issuer: string | IIssuer
453
+ proofFormat: CredentialProofFormat
454
+ keyRef?: string
455
+ },
456
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
457
+ ): Promise<BitstringStatusListCredential> {
458
+ const { unsignedCredential, issuer, proofFormat, keyRef } = args
459
+
460
+ const identifier = await context.agent.identifierManagedGet({
461
+ identifier: typeof issuer === 'string' ? issuer : issuer.id,
462
+ vmRelationship: 'assertionMethod',
463
+ offlineWhenNoDIDRegistered: true,
464
+ })
465
+
466
+ const verifiableCredential = await context.agent.createVerifiableCredential({
467
+ credential: unsignedCredential,
468
+ keyRef: keyRef ?? identifier.kmsKeyRef,
469
+ proofFormat,
470
+ fetchRemoteContexts: true,
471
+ })
472
+
473
+ return CredentialMapper.toWrappedVerifiableCredential(verifiableCredential as StatusListCredential).original as BitstringStatusListCredential
474
+ }
475
+
476
+ /**
477
+ * Builds the appropriate content type string for a given proof format
478
+ *
479
+ * @param proofFormat - The proof format to build content type for
480
+ * @returns The corresponding content type string
481
+ */
482
+ private buildContentType(proofFormat: CredentialProofFormat | undefined): string {
483
+ switch (proofFormat) {
484
+ case 'jwt':
485
+ return 'application/statuslist+jwt'
486
+ case 'cbor':
487
+ return 'application/statuslist+cwt'
488
+ case 'vc+jwt':
489
+ return 'application/statuslist+vc+jwt'
490
+ case 'lds':
491
+ return 'application/statuslist+ld+json'
492
+ default:
493
+ throw Error(`Unsupported content type '${proofFormat}' for status lists`)
494
+ }
495
+ }
496
+ }
@@ -1,33 +1,64 @@
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
- import type {
3
+ import {
4
4
  CheckStatusIndexArgs,
5
5
  CreateStatusListArgs,
6
+ IMergeDetailsWithEntityArgs,
7
+ IToDetailsFromCredentialArgs,
6
8
  Status2021,
9
+ StatusList2021EntryCredentialStatus,
10
+ StatusListOAuthEntryCredentialStatus,
7
11
  StatusListResult,
8
12
  StatusOAuth,
9
- ToStatusListDetailsArgs,
10
13
  UpdateStatusListFromEncodedListArgs,
11
14
  UpdateStatusListIndexArgs,
12
15
  } from '../types'
16
+ import { BitstringStatusPurpose } from '@4sure-tech/vc-bitstring-status-lists'
17
+ import {
18
+ CredentialProofFormat,
19
+ IIssuer,
20
+ StatusListCredential,
21
+ StatusListDriverType,
22
+ StatusListIndexingDirection,
23
+ StatusListType,
24
+ StatusPurpose2021,
25
+ } from '@sphereon/ssi-types'
26
+ import {
27
+ BitstringStatusListEntryCredentialStatus,
28
+ IBitstringStatusListEntryEntity,
29
+ IStatusListEntryEntity,
30
+ StatusListEntity,
31
+ } from '@sphereon/ssi-sdk.data-store'
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
+ }
13
41
 
14
42
  export interface IStatusList {
15
43
  /**
16
44
  * Creates a new status list of the specific type
17
45
  */
18
- createNewStatusList(args: CreateStatusListArgs, context: IAgentContext<ICredentialPlugin & IIdentifierResolution>): Promise<StatusListResult>
46
+ createNewStatusList(args: CreateStatusListArgs, context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>): Promise<StatusListResult>
19
47
 
20
48
  /**
21
49
  * Updates a status at the given index in the status list
22
50
  */
23
- updateStatusListIndex(args: UpdateStatusListIndexArgs, context: IAgentContext<ICredentialPlugin & IIdentifierResolution>): Promise<StatusListResult>
51
+ updateStatusListIndex(
52
+ args: UpdateStatusListIndexArgs,
53
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
54
+ ): Promise<StatusListResult>
24
55
 
25
56
  /**
26
57
  * Updates a status list using a base64 encoded list of statuses
27
58
  */
28
59
  updateStatusListFromEncodedList(
29
60
  args: UpdateStatusListFromEncodedListArgs,
30
- context: IAgentContext<ICredentialPlugin & IIdentifierResolution>,
61
+ context: IAgentContext<IVcdmCredentialPlugin & IIdentifierResolution>,
31
62
  ): Promise<StatusListResult>
32
63
 
33
64
  /**
@@ -36,7 +67,70 @@ export interface IStatusList {
36
67
  checkStatusIndex(args: CheckStatusIndexArgs): Promise<number | Status2021 | StatusOAuth>
37
68
 
38
69
  /**
39
- * Collects the status list details
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
+ >
84
+
85
+ /**
86
+ * Merges pre-parsed details from a new credential with an existing database entity.
87
+ */
88
+ toStatusListDetails(
89
+ args: IMergeDetailsWithEntityArgs,
90
+ ): Promise<
91
+ StatusListResult & (IStatusList2021ImplementationResult | IOAuthStatusListImplementationResult | IBitstringStatusListImplementationResult)
92
+ >
93
+
94
+ /**
95
+ * Creates a credential status object from a status list and entry
40
96
  */
41
- toStatusListDetails(args: ToStatusListDetailsArgs): Promise<StatusListResult>
97
+ createCredentialStatus(args: {
98
+ statusList: StatusListEntity
99
+ statusListEntry: IStatusListEntryEntity | IBitstringStatusListEntryEntity
100
+ statusListIndex: number
101
+ }): Promise<StatusList2021EntryCredentialStatus | StatusListOAuthEntryCredentialStatus | BitstringStatusListEntryCredentialStatus>
102
+ }
103
+
104
+ export interface IStatusListImplementationResult {
105
+ id: string
106
+ encodedList: string
107
+ issuer: string | IIssuer
108
+ type: StatusListType
109
+ proofFormat: CredentialProofFormat
110
+ length: number
111
+ statusListCredential: StatusListCredential
112
+ statuslistContentType: string
113
+ correlationId?: string
114
+ driverType?: StatusListDriverType
115
+ }
116
+
117
+ export interface IStatusList2021ImplementationResult extends IStatusListImplementationResult {
118
+ type: StatusListType.StatusList2021
119
+ indexingDirection: StatusListIndexingDirection
120
+ statusPurpose: StatusPurpose2021
121
+ }
122
+
123
+ export interface IOAuthStatusListImplementationResult extends IStatusListImplementationResult {
124
+ type: StatusListType.OAuthStatusList
125
+ bitsPerStatus: number
126
+ expiresAt?: Date
127
+ }
128
+
129
+ export interface IBitstringStatusListImplementationResult extends IStatusListImplementationResult {
130
+ type: StatusListType.BitstringStatusList
131
+ statusPurpose: BitstringStatusPurpose | BitstringStatusPurpose[]
132
+ bitsPerStatus?: number
133
+ validFrom?: Date
134
+ validUntil?: Date
135
+ ttl?: number
42
136
  }