@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/dist/index.cjs +303 -159
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +117 -43
- package/dist/index.d.ts +117 -43
- package/dist/index.js +303 -159
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/functions.ts +100 -36
- package/src/impl/BitstringStatusListImplementation.ts +117 -65
- package/src/impl/IStatusList.ts +35 -7
- package/src/impl/OAuthStatusList.ts +82 -30
- package/src/impl/StatusList2021.ts +78 -34
- package/src/index.ts +1 -0
- package/src/types/index.ts +18 -39
- package/src/utils.ts +47 -18
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.
|
|
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.
|
|
35
|
-
"@sphereon/ssi-sdk.data-store": "0.34.1-feature.SSISDK.17.bitstring.sl.
|
|
36
|
-
"@sphereon/ssi-types": "0.34.1-feature.SSISDK.17.bitstring.sl.
|
|
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": "
|
|
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 {
|
|
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
|
|
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
|
|
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
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
|
|
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 {
|
|
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 = '
|
|
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
|
-
|
|
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<
|
|
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
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
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
|
|
302
|
-
const
|
|
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
|
|
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
|
-
|
|
321
|
-
id,
|
|
322
|
-
encodedList,
|
|
312
|
+
id: getAssertedValue('id', uniform.id),
|
|
323
313
|
issuer,
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|
-
|
|
340
|
-
|
|
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
|
-
|
|
349
|
-
|
|
350
|
-
|
|
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:
|
|
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
|
|
package/src/impl/IStatusList.ts
CHANGED
|
@@ -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 {
|
|
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
|
|
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
|
-
*
|
|
86
|
+
* Merges pre-parsed details from a new credential with an existing database entity.
|
|
59
87
|
*/
|
|
60
88
|
toStatusListDetails(
|
|
61
|
-
args:
|
|
89
|
+
args: IMergeDetailsWithEntityArgs,
|
|
62
90
|
): Promise<
|
|
63
91
|
StatusListResult & (IStatusList2021ImplementationResult | IOAuthStatusListImplementationResult | IBitstringStatusListImplementationResult)
|
|
64
92
|
>
|