@sphereon/ssi-sdk.vc-status-list 0.34.1-feature.SSISDK.17.bitstring.sl.10 → 0.34.1-feature.SSISDK.17.bitstring.sl.11
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 +120 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -24
- package/dist/index.d.ts +33 -24
- package/dist/index.js +120 -21
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/functions.ts +31 -4
- package/src/impl/BitstringStatusListImplementation.ts +51 -5
- package/src/impl/IStatusList.ts +63 -2
- package/src/impl/OAuthStatusList.ts +44 -8
- package/src/impl/StatusList2021.ts +44 -9
- package/src/types/index.ts +28 -23
package/src/functions.ts
CHANGED
|
@@ -10,15 +10,20 @@ import {
|
|
|
10
10
|
} from '@sphereon/ssi-types'
|
|
11
11
|
import type { CredentialStatus, DIDDocument, IAgentContext, ICredentialPlugin, ProofFormat as VeramoProofFormat } from '@veramo/core'
|
|
12
12
|
|
|
13
|
+
import { IAddStatusListArgs, IBitstringStatusListEntryEntity, IStatusListEntryEntity, StatusListEntity } from '@sphereon/ssi-sdk.data-store'
|
|
14
|
+
|
|
13
15
|
import { checkStatus } from '@sphereon/vc-status-list'
|
|
14
16
|
|
|
15
17
|
// @ts-ignore
|
|
16
18
|
import { CredentialJwtOrJSON, StatusMethod } from 'credential-status'
|
|
17
19
|
import {
|
|
18
20
|
BitstringStatus,
|
|
21
|
+
BitstringStatusListEntryCredentialStatus,
|
|
19
22
|
CreateNewStatusListFuncArgs,
|
|
20
23
|
Status2021,
|
|
24
|
+
StatusList2021EntryCredentialStatus,
|
|
21
25
|
StatusList2021ToVerifiableCredentialArgs,
|
|
26
|
+
StatusListOAuthEntryCredentialStatus,
|
|
22
27
|
StatusListResult,
|
|
23
28
|
StatusOAuth,
|
|
24
29
|
UpdateStatusListFromEncodedListArgs,
|
|
@@ -146,7 +151,7 @@ export async function simpleCheckStatusFromStatusListUrl(args: {
|
|
|
146
151
|
|
|
147
152
|
export async function checkStatusIndexFromStatusListCredential(args: {
|
|
148
153
|
statusListCredential: StatusListCredential
|
|
149
|
-
statusPurpose?: StatusPurpose2021
|
|
154
|
+
statusPurpose?: StatusPurpose2021 | string | string[]
|
|
150
155
|
type?: StatusListType | 'StatusList2021Entry' | 'BitstringStatusListEntry'
|
|
151
156
|
id?: string
|
|
152
157
|
statusListIndex: string | number
|
|
@@ -176,7 +181,6 @@ export async function updateStatusIndexFromStatusListCredential(
|
|
|
176
181
|
return implementation.updateStatusListIndex(args, context)
|
|
177
182
|
}
|
|
178
183
|
|
|
179
|
-
// Keeping helper function for backward compatibility
|
|
180
184
|
export async function statusListCredentialToDetails({
|
|
181
185
|
correlationId,
|
|
182
186
|
driverType,
|
|
@@ -187,7 +191,7 @@ export async function statusListCredentialToDetails({
|
|
|
187
191
|
correlationId?: string
|
|
188
192
|
driverType?: StatusListDriverType
|
|
189
193
|
bitsPerStatus?: number
|
|
190
|
-
}): Promise<StatusListResult
|
|
194
|
+
}): Promise<StatusListResult & Partial<IAddStatusListArgs>> {
|
|
191
195
|
const credential = getAssertedValue('statusListCredential', statusListCredential)
|
|
192
196
|
|
|
193
197
|
let statusListType: StatusListType | undefined
|
|
@@ -213,12 +217,35 @@ export async function statusListCredentialToDetails({
|
|
|
213
217
|
}
|
|
214
218
|
|
|
215
219
|
const implementation = getStatusListImplementation(statusListType)
|
|
216
|
-
|
|
220
|
+
|
|
221
|
+
// The implementation should now return all the type-specific fields needed for the entity
|
|
222
|
+
const result = await implementation.toStatusListDetails({
|
|
217
223
|
statusListPayload: credential,
|
|
218
224
|
correlationId: correlationId,
|
|
219
225
|
driverType: driverType,
|
|
220
226
|
bitsPerStatus: bitsPerStatus,
|
|
221
227
|
})
|
|
228
|
+
|
|
229
|
+
return result
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export async function createCredentialStatusFromStatusList(args: {
|
|
233
|
+
statusList: StatusListEntity
|
|
234
|
+
statusListEntry: IStatusListEntryEntity | IBitstringStatusListEntryEntity
|
|
235
|
+
statusListIndex: number
|
|
236
|
+
}): Promise<StatusList2021EntryCredentialStatus | StatusListOAuthEntryCredentialStatus | BitstringStatusListEntryCredentialStatus> {
|
|
237
|
+
const { statusList, statusListEntry, statusListIndex } = args
|
|
238
|
+
|
|
239
|
+
// Determine the status list type and delegate to appropriate implementation
|
|
240
|
+
const statusListType = determineStatusListType(statusList.statusListCredential!)
|
|
241
|
+
const implementation = getStatusListImplementation(statusListType)
|
|
242
|
+
|
|
243
|
+
// Each implementation should have a method to create credential status
|
|
244
|
+
return implementation.createCredentialStatus({
|
|
245
|
+
statusList,
|
|
246
|
+
statusListEntry,
|
|
247
|
+
statusListIndex,
|
|
248
|
+
})
|
|
222
249
|
}
|
|
223
250
|
|
|
224
251
|
export async function updateStatusListIndexFromEncodedList(
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { IAgentContext, ICredentialPlugin, ProofFormat as VeramoProofFormat } from '@veramo/core'
|
|
2
2
|
import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
3
|
+
|
|
3
4
|
import {
|
|
4
5
|
CredentialMapper,
|
|
5
6
|
type CredentialProofFormat,
|
|
@@ -9,9 +10,10 @@ import {
|
|
|
9
10
|
StatusListType,
|
|
10
11
|
} from '@sphereon/ssi-types'
|
|
11
12
|
|
|
12
|
-
import type { IStatusList } from './IStatusList'
|
|
13
|
+
import type { IBitstringStatusListImplementationResult, IStatusList } from './IStatusList'
|
|
13
14
|
import {
|
|
14
15
|
BitstringStatus,
|
|
16
|
+
BitstringStatusListEntryCredentialStatus,
|
|
15
17
|
CheckStatusIndexArgs,
|
|
16
18
|
CreateStatusListArgs,
|
|
17
19
|
StatusListResult,
|
|
@@ -23,6 +25,7 @@ import {
|
|
|
23
25
|
import { assertValidProofType, ensureDate, getAssertedProperty, getAssertedValue, getAssertedValues } from '../utils'
|
|
24
26
|
import { BitstringStatusListCredential } from '../types/BitstringStatusList'
|
|
25
27
|
import { BitstreamStatusList, BitstringStatusPurpose, createStatusListCredential } from '@4sure-tech/vc-bitstring-status-lists'
|
|
28
|
+
import { BitstringStatusListEntity, IBitstringStatusListEntryEntity, IStatusListEntryEntity, StatusListEntity } from '@sphereon/ssi-sdk.data-store'
|
|
26
29
|
|
|
27
30
|
export const DEFAULT_LIST_LENGTH = 131072 // W3C spec minimum
|
|
28
31
|
export const DEFAULT_PROOF_FORMAT = 'lds' as CredentialProofFormat
|
|
@@ -215,7 +218,7 @@ export class BitstringStatusListImplementation implements IStatusList {
|
|
|
215
218
|
return statusList.getStatus(numIndex)
|
|
216
219
|
}
|
|
217
220
|
|
|
218
|
-
async toStatusListDetails(args: ToStatusListDetailsArgs): Promise<StatusListResult> {
|
|
221
|
+
async toStatusListDetails(args: ToStatusListDetailsArgs): Promise<StatusListResult & IBitstringStatusListImplementationResult> {
|
|
219
222
|
const { statusListPayload, bitsPerStatus } = args
|
|
220
223
|
if (!bitsPerStatus || bitsPerStatus < 1) {
|
|
221
224
|
return Promise.reject('bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (toStatusListDetails)')
|
|
@@ -234,6 +237,7 @@ export class BitstringStatusListImplementation implements IStatusList {
|
|
|
234
237
|
const statuslistLength: number = BitstreamStatusList.getStatusListLength(encodedList, bitsPerStatus)
|
|
235
238
|
|
|
236
239
|
return {
|
|
240
|
+
// Base implementation fields
|
|
237
241
|
id,
|
|
238
242
|
encodedList,
|
|
239
243
|
issuer,
|
|
@@ -242,18 +246,60 @@ export class BitstringStatusListImplementation implements IStatusList {
|
|
|
242
246
|
length: statuslistLength,
|
|
243
247
|
statusListCredential: statusListPayload,
|
|
244
248
|
statuslistContentType: this.buildContentType(proofFormat),
|
|
249
|
+
correlationId: args.correlationId, // FIXME these do not need to be inside the impl
|
|
250
|
+
driverType: args.driverType, // FIXME these do not need to be inside the impl
|
|
251
|
+
|
|
252
|
+
// Flattened Bitstring-specific fields
|
|
253
|
+
statusPurpose,
|
|
254
|
+
bitsPerStatus,
|
|
255
|
+
...(validFrom && { validFrom }),
|
|
256
|
+
...(validUntil && { validUntil }),
|
|
257
|
+
...(ttl && { ttl }),
|
|
258
|
+
|
|
259
|
+
// Legacy nested structure for backward compatibility
|
|
245
260
|
bitstringStatusList: {
|
|
246
261
|
statusPurpose,
|
|
247
262
|
bitsPerStatus,
|
|
248
|
-
validFrom,
|
|
249
|
-
validUntil,
|
|
250
|
-
ttl,
|
|
263
|
+
...(validFrom && { validFrom }),
|
|
264
|
+
...(validUntil && { validUntil }),
|
|
265
|
+
...(ttl && { ttl }),
|
|
251
266
|
},
|
|
267
|
+
|
|
268
|
+
// Optional fields from args
|
|
252
269
|
...(args.correlationId && { correlationId: args.correlationId }),
|
|
253
270
|
...(args.driverType && { driverType: args.driverType }),
|
|
254
271
|
}
|
|
255
272
|
}
|
|
256
273
|
|
|
274
|
+
async createCredentialStatus(args: {
|
|
275
|
+
statusList: StatusListEntity
|
|
276
|
+
statusListEntry: IStatusListEntryEntity | IBitstringStatusListEntryEntity
|
|
277
|
+
statusListIndex: number
|
|
278
|
+
}): Promise<BitstringStatusListEntryCredentialStatus> {
|
|
279
|
+
const { statusList, statusListEntry, statusListIndex } = args
|
|
280
|
+
|
|
281
|
+
// Type guard to ensure we have a bitstring entry
|
|
282
|
+
const isBitstringEntry = (entry: IStatusListEntryEntity | IBitstringStatusListEntryEntity): entry is IBitstringStatusListEntryEntity => {
|
|
283
|
+
return 'statusPurpose' in entry
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (!isBitstringEntry(statusListEntry)) {
|
|
287
|
+
throw new Error('Expected bitstring status list entry for bitstring status list')
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Cast to BitstringStatusListEntity to access specific properties
|
|
291
|
+
const bitstringStatusList = statusList as BitstringStatusListEntity
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
id: `${statusList.id}#${statusListIndex}`,
|
|
295
|
+
type: 'BitstringStatusListEntry',
|
|
296
|
+
statusPurpose: statusListEntry.statusPurpose,
|
|
297
|
+
statusListIndex: '' + statusListIndex,
|
|
298
|
+
statusListCredential: statusList.id,
|
|
299
|
+
bitsPerStatus: bitstringStatusList.bitsPerStatus,
|
|
300
|
+
} satisfies BitstringStatusListEntryCredentialStatus
|
|
301
|
+
}
|
|
302
|
+
|
|
257
303
|
private async createVerifiableCredential(
|
|
258
304
|
args: {
|
|
259
305
|
id: string
|
package/src/impl/IStatusList.ts
CHANGED
|
@@ -2,15 +2,29 @@ import type { IAgentContext, ICredentialPlugin } from '@veramo/core'
|
|
|
2
2
|
import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
3
3
|
import {
|
|
4
4
|
BitstringStatus,
|
|
5
|
+
BitstringStatusListEntryCredentialStatus,
|
|
5
6
|
CheckStatusIndexArgs,
|
|
6
7
|
CreateStatusListArgs,
|
|
7
8
|
Status2021,
|
|
9
|
+
StatusList2021EntryCredentialStatus,
|
|
10
|
+
StatusListOAuthEntryCredentialStatus,
|
|
8
11
|
StatusListResult,
|
|
9
12
|
StatusOAuth,
|
|
10
13
|
ToStatusListDetailsArgs,
|
|
11
14
|
UpdateStatusListFromEncodedListArgs,
|
|
12
15
|
UpdateStatusListIndexArgs,
|
|
13
16
|
} from '../types'
|
|
17
|
+
import { BitstringStatusPurpose } from '@4sure-tech/vc-bitstring-status-lists'
|
|
18
|
+
import {
|
|
19
|
+
CredentialProofFormat,
|
|
20
|
+
IIssuer,
|
|
21
|
+
StatusListCredential,
|
|
22
|
+
StatusListDriverType,
|
|
23
|
+
StatusListIndexingDirection,
|
|
24
|
+
StatusListType,
|
|
25
|
+
StatusPurpose2021,
|
|
26
|
+
} from '@sphereon/ssi-types'
|
|
27
|
+
import { IBitstringStatusListEntryEntity, IStatusListEntryEntity, StatusListEntity } from '@sphereon/ssi-sdk.data-store'
|
|
14
28
|
|
|
15
29
|
export interface IStatusList {
|
|
16
30
|
/**
|
|
@@ -37,7 +51,54 @@ export interface IStatusList {
|
|
|
37
51
|
checkStatusIndex(args: CheckStatusIndexArgs): Promise<number | Status2021 | StatusOAuth | BitstringStatus>
|
|
38
52
|
|
|
39
53
|
/**
|
|
40
|
-
* Collects the status list details
|
|
54
|
+
* Collects the status list details - returns flattened entity data ready for storage
|
|
55
|
+
*/
|
|
56
|
+
toStatusListDetails(
|
|
57
|
+
args: ToStatusListDetailsArgs,
|
|
58
|
+
): Promise<
|
|
59
|
+
StatusListResult & (IStatusList2021ImplementationResult | IOAuthStatusListImplementationResult | IBitstringStatusListImplementationResult)
|
|
60
|
+
>
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Creates a credential status object from a status list and entry
|
|
41
64
|
*/
|
|
42
|
-
|
|
65
|
+
createCredentialStatus(args: {
|
|
66
|
+
statusList: StatusListEntity
|
|
67
|
+
statusListEntry: IStatusListEntryEntity | IBitstringStatusListEntryEntity
|
|
68
|
+
statusListIndex: number
|
|
69
|
+
}): Promise<StatusList2021EntryCredentialStatus | StatusListOAuthEntryCredentialStatus | BitstringStatusListEntryCredentialStatus>
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface IStatusListImplementationResult {
|
|
73
|
+
id: string
|
|
74
|
+
encodedList: string
|
|
75
|
+
issuer: string | IIssuer
|
|
76
|
+
type: StatusListType
|
|
77
|
+
proofFormat: CredentialProofFormat
|
|
78
|
+
length: number
|
|
79
|
+
statusListCredential: StatusListCredential
|
|
80
|
+
statuslistContentType: string
|
|
81
|
+
correlationId?: string
|
|
82
|
+
driverType?: StatusListDriverType
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface IStatusList2021ImplementationResult extends IStatusListImplementationResult {
|
|
86
|
+
type: StatusListType.StatusList2021
|
|
87
|
+
indexingDirection: StatusListIndexingDirection
|
|
88
|
+
statusPurpose: StatusPurpose2021
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface IOAuthStatusListImplementationResult extends IStatusListImplementationResult {
|
|
92
|
+
type: StatusListType.OAuthStatusList
|
|
93
|
+
bitsPerStatus: number
|
|
94
|
+
expiresAt?: Date
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface IBitstringStatusListImplementationResult extends IStatusListImplementationResult {
|
|
98
|
+
type: StatusListType.BitstringStatusList
|
|
99
|
+
statusPurpose: BitstringStatusPurpose | BitstringStatusPurpose[]
|
|
100
|
+
bitsPerStatus?: number
|
|
101
|
+
validFrom?: Date
|
|
102
|
+
validUntil?: Date
|
|
103
|
+
ttl?: number
|
|
43
104
|
}
|
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
CheckStatusIndexArgs,
|
|
5
5
|
CreateStatusListArgs,
|
|
6
6
|
SignedStatusListData,
|
|
7
|
+
StatusListOAuthEntryCredentialStatus,
|
|
7
8
|
StatusListResult,
|
|
8
9
|
StatusOAuth,
|
|
9
10
|
ToStatusListDetailsArgs,
|
|
@@ -11,12 +12,13 @@ import type {
|
|
|
11
12
|
UpdateStatusListIndexArgs,
|
|
12
13
|
} from '../types'
|
|
13
14
|
import { determineProofFormat, ensureDate, getAssertedValue, getAssertedValues } from '../utils'
|
|
14
|
-
import type { IStatusList } from './IStatusList'
|
|
15
|
+
import type { IOAuthStatusListImplementationResult, IStatusList } from './IStatusList'
|
|
15
16
|
import { StatusList } from '@sd-jwt/jwt-status-list'
|
|
16
17
|
import type { IJwtService } from '@sphereon/ssi-sdk-ext.jwt-service'
|
|
17
18
|
import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
18
19
|
import { createSignedJwt, decodeStatusListJWT } from './encoding/jwt'
|
|
19
20
|
import { createSignedCbor, decodeStatusListCWT } from './encoding/cbor'
|
|
21
|
+
import { IBitstringStatusListEntryEntity, IStatusListEntryEntity, OAuthStatusListEntity, StatusListEntity } from '@sphereon/ssi-sdk.data-store'
|
|
20
22
|
|
|
21
23
|
type IRequiredContext = IAgentContext<ICredentialPlugin & IJwtService & IIdentifierResolution & IKeyManager>
|
|
22
24
|
|
|
@@ -144,10 +146,6 @@ export class OAuthStatusListImplementation implements IStatusList {
|
|
|
144
146
|
}
|
|
145
147
|
}
|
|
146
148
|
|
|
147
|
-
private buildContentType(proofFormat: CredentialProofFormat | undefined) {
|
|
148
|
-
return `application/statuslist+${proofFormat === 'cbor' ? 'cwt' : 'jwt'}`
|
|
149
|
-
}
|
|
150
|
-
|
|
151
149
|
async checkStatusIndex(args: CheckStatusIndexArgs): Promise<number | StatusOAuth> {
|
|
152
150
|
const { statusListCredential, statusListIndex } = args
|
|
153
151
|
if (typeof statusListCredential !== 'string') {
|
|
@@ -165,13 +163,17 @@ export class OAuthStatusListImplementation implements IStatusList {
|
|
|
165
163
|
return statusList.getStatus(index)
|
|
166
164
|
}
|
|
167
165
|
|
|
168
|
-
async toStatusListDetails(args: ToStatusListDetailsArgs): Promise<StatusListResult> {
|
|
166
|
+
async toStatusListDetails(args: ToStatusListDetailsArgs): Promise<StatusListResult & IOAuthStatusListImplementationResult> {
|
|
169
167
|
const { statusListPayload } = args as { statusListPayload: CompactJWT | CWT }
|
|
170
168
|
const proofFormat = determineProofFormat(statusListPayload)
|
|
171
169
|
const decoded = proofFormat === 'jwt' ? decodeStatusListJWT(statusListPayload) : decodeStatusListCWT(statusListPayload)
|
|
172
170
|
const { statusList, issuer, id, exp } = decoded
|
|
173
171
|
|
|
172
|
+
const bitsPerStatus = statusList.getBitsPerStatus()
|
|
173
|
+
const expiresAt = exp ? new Date(exp * 1000) : undefined
|
|
174
|
+
|
|
174
175
|
return {
|
|
176
|
+
// Base implementation fields
|
|
175
177
|
id,
|
|
176
178
|
encodedList: statusList.compressStatusList(),
|
|
177
179
|
issuer,
|
|
@@ -180,15 +182,49 @@ export class OAuthStatusListImplementation implements IStatusList {
|
|
|
180
182
|
length: statusList.statusList.length,
|
|
181
183
|
statusListCredential: statusListPayload,
|
|
182
184
|
statuslistContentType: this.buildContentType(proofFormat),
|
|
185
|
+
correlationId: args.correlationId, // FIXME these do not need to be inside the impl
|
|
186
|
+
driverType: args.driverType, // FIXME these do not need to be inside the impl
|
|
187
|
+
|
|
188
|
+
// Flattened OAuth-specific fields
|
|
189
|
+
bitsPerStatus,
|
|
190
|
+
...(expiresAt && { expiresAt }),
|
|
191
|
+
|
|
192
|
+
// Legacy nested structure for backward compatibility
|
|
183
193
|
oauthStatusList: {
|
|
184
|
-
bitsPerStatus
|
|
185
|
-
...(
|
|
194
|
+
bitsPerStatus,
|
|
195
|
+
...(expiresAt && { expiresAt }),
|
|
186
196
|
},
|
|
197
|
+
|
|
198
|
+
// Optional fields from args
|
|
187
199
|
...(args.correlationId && { correlationId: args.correlationId }),
|
|
188
200
|
...(args.driverType && { driverType: args.driverType }),
|
|
189
201
|
}
|
|
190
202
|
}
|
|
191
203
|
|
|
204
|
+
async createCredentialStatus(args: {
|
|
205
|
+
statusList: StatusListEntity
|
|
206
|
+
statusListEntry: IStatusListEntryEntity | IBitstringStatusListEntryEntity
|
|
207
|
+
statusListIndex: number
|
|
208
|
+
}): Promise<StatusListOAuthEntryCredentialStatus> {
|
|
209
|
+
const { statusList, statusListIndex } = args
|
|
210
|
+
|
|
211
|
+
// Cast to OAuthStatusListEntity to access specific properties
|
|
212
|
+
const oauthStatusList = statusList as OAuthStatusListEntity
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
id: `${statusList.id}#${statusListIndex}`,
|
|
216
|
+
type: 'OAuthStatusListEntry',
|
|
217
|
+
bitsPerStatus: oauthStatusList.bitsPerStatus,
|
|
218
|
+
statusListIndex: '' + statusListIndex,
|
|
219
|
+
statusListCredential: statusList.id,
|
|
220
|
+
expiresAt: oauthStatusList.expiresAt,
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
private buildContentType(proofFormat: CredentialProofFormat | undefined) {
|
|
225
|
+
return `application/statuslist+${proofFormat === 'cbor' ? 'cwt' : 'jwt'}`
|
|
226
|
+
}
|
|
227
|
+
|
|
192
228
|
private async createSignedStatusList(
|
|
193
229
|
proofFormat: CredentialProofFormat,
|
|
194
230
|
context: IAgentContext<ICredentialPlugin & IJwtService & IIdentifierResolution & IKeyManager>,
|
|
@@ -2,15 +2,15 @@ import type { IAgentContext, ICredentialPlugin, ProofFormat as VeramoProofFormat
|
|
|
2
2
|
import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
3
3
|
import {
|
|
4
4
|
CredentialMapper,
|
|
5
|
+
type CredentialProofFormat,
|
|
5
6
|
DocumentFormat,
|
|
6
7
|
type IIssuer,
|
|
7
|
-
type CredentialProofFormat,
|
|
8
8
|
type StatusListCredential,
|
|
9
9
|
StatusListType,
|
|
10
10
|
} from '@sphereon/ssi-types'
|
|
11
11
|
|
|
12
12
|
import { StatusList } from '@sphereon/vc-status-list'
|
|
13
|
-
import type { IStatusList } from './IStatusList'
|
|
13
|
+
import type { IStatusList, IStatusList2021ImplementationResult } from './IStatusList'
|
|
14
14
|
import type {
|
|
15
15
|
CheckStatusIndexArgs,
|
|
16
16
|
CreateStatusListArgs,
|
|
@@ -19,9 +19,9 @@ import type {
|
|
|
19
19
|
UpdateStatusListFromEncodedListArgs,
|
|
20
20
|
UpdateStatusListIndexArgs,
|
|
21
21
|
} from '../types'
|
|
22
|
-
|
|
23
|
-
import { Status2021 } from '../types'
|
|
22
|
+
import { Status2021, StatusList2021EntryCredentialStatus } from '../types'
|
|
24
23
|
import { assertValidProofType, getAssertedProperty, getAssertedValue, getAssertedValues } from '../utils'
|
|
24
|
+
import { IBitstringStatusListEntryEntity, IStatusListEntryEntity, StatusList2021Entity, StatusListEntity } from '@sphereon/ssi-sdk.data-store'
|
|
25
25
|
|
|
26
26
|
export const DEFAULT_LIST_LENGTH = 250000
|
|
27
27
|
export const DEFAULT_PROOF_FORMAT = 'lds' as CredentialProofFormat
|
|
@@ -96,11 +96,15 @@ export class StatusList2021Implementation implements IStatusList {
|
|
|
96
96
|
context,
|
|
97
97
|
)
|
|
98
98
|
|
|
99
|
+
if (!('statusPurpose' in credentialSubject)) {
|
|
100
|
+
return Promise.reject(Error('statusPurpose is required in credentialSubject for StatusList2021'))
|
|
101
|
+
}
|
|
102
|
+
|
|
99
103
|
return {
|
|
100
104
|
statusListCredential: updatedCredential,
|
|
101
105
|
encodedList,
|
|
102
106
|
statusList2021: {
|
|
103
|
-
|
|
107
|
+
statusPurpose: credentialSubject.statusPurpose,
|
|
104
108
|
indexingDirection: 'rightToLeft',
|
|
105
109
|
},
|
|
106
110
|
length: statusList.length - 1,
|
|
@@ -166,7 +170,7 @@ export class StatusList2021Implementation implements IStatusList {
|
|
|
166
170
|
return status ? Status2021.Invalid : Status2021.Valid
|
|
167
171
|
}
|
|
168
172
|
|
|
169
|
-
async toStatusListDetails(args: ToStatusListDetailsArgs): Promise<StatusListResult> {
|
|
173
|
+
async toStatusListDetails(args: ToStatusListDetailsArgs): Promise<StatusListResult & IStatusList2021ImplementationResult> {
|
|
170
174
|
const { statusListPayload } = args
|
|
171
175
|
const uniform = CredentialMapper.toUniformCredential(statusListPayload)
|
|
172
176
|
const { issuer, credentialSubject } = uniform
|
|
@@ -175,9 +179,11 @@ export class StatusList2021Implementation implements IStatusList {
|
|
|
175
179
|
const proofFormat: CredentialProofFormat = CredentialMapper.detectDocumentType(statusListPayload) === DocumentFormat.JWT ? 'jwt' : 'lds'
|
|
176
180
|
|
|
177
181
|
const statusPurpose = getAssertedProperty('statusPurpose', credentialSubject)
|
|
182
|
+
const indexingDirection = 'rightToLeft'
|
|
178
183
|
const list = await StatusList.decode({ encodedList })
|
|
179
184
|
|
|
180
185
|
return {
|
|
186
|
+
// Base implementation fields
|
|
181
187
|
id,
|
|
182
188
|
encodedList,
|
|
183
189
|
issuer,
|
|
@@ -186,12 +192,41 @@ export class StatusList2021Implementation implements IStatusList {
|
|
|
186
192
|
length: list.length,
|
|
187
193
|
statusListCredential: statusListPayload,
|
|
188
194
|
statuslistContentType: this.buildContentType(proofFormat),
|
|
195
|
+
correlationId: args.correlationId, // FIXME these do not need to be inside the impl
|
|
196
|
+
driverType: args.driverType, // FIXME these do not need to be inside the impl
|
|
197
|
+
|
|
198
|
+
// Flattened StatusList2021-specific fields
|
|
199
|
+
indexingDirection,
|
|
200
|
+
statusPurpose,
|
|
201
|
+
|
|
202
|
+
// Legacy nested structure for backward compatibility
|
|
189
203
|
statusList2021: {
|
|
190
|
-
indexingDirection
|
|
204
|
+
indexingDirection,
|
|
191
205
|
statusPurpose,
|
|
206
|
+
|
|
207
|
+
// Optional fields from args
|
|
208
|
+
...(args.correlationId && { correlationId: args.correlationId }),
|
|
209
|
+
...(args.driverType && { driverType: args.driverType }),
|
|
192
210
|
},
|
|
193
|
-
|
|
194
|
-
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async createCredentialStatus(args: {
|
|
215
|
+
statusList: StatusListEntity
|
|
216
|
+
statusListEntry: IStatusListEntryEntity | IBitstringStatusListEntryEntity
|
|
217
|
+
statusListIndex: number
|
|
218
|
+
}): Promise<StatusList2021EntryCredentialStatus> {
|
|
219
|
+
const { statusList, statusListIndex } = args
|
|
220
|
+
|
|
221
|
+
// Cast to StatusList2021Entity to access specific properties
|
|
222
|
+
const statusList2021 = statusList as StatusList2021Entity
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
id: `${statusList.id}#${statusListIndex}`,
|
|
226
|
+
type: 'StatusList2021Entry',
|
|
227
|
+
statusPurpose: statusList2021.statusPurpose ?? 'revocation',
|
|
228
|
+
statusListIndex: '' + statusListIndex,
|
|
229
|
+
statusListCredential: statusList.id,
|
|
195
230
|
}
|
|
196
231
|
}
|
|
197
232
|
|
package/src/types/index.ts
CHANGED
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
type IVerifiableCredential,
|
|
8
8
|
type OrPromise,
|
|
9
9
|
type StatusListCredential,
|
|
10
|
-
StatusListCredentialIdMode,
|
|
11
10
|
StatusListDriverType,
|
|
12
11
|
type StatusListIndexingDirection,
|
|
13
12
|
StatusListType,
|
|
@@ -48,7 +47,7 @@ export type StatusList2021Args = {
|
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
export type OAuthStatusListArgs = {
|
|
51
|
-
bitsPerStatus
|
|
50
|
+
bitsPerStatus: BitsPerStatus
|
|
52
51
|
expiresAt?: Date
|
|
53
52
|
}
|
|
54
53
|
|
|
@@ -114,40 +113,46 @@ export interface UpdateStatusListFromStatusListCredentialArgs {
|
|
|
114
113
|
}
|
|
115
114
|
|
|
116
115
|
export interface StatusListResult {
|
|
116
|
+
id: string
|
|
117
117
|
encodedList: string
|
|
118
|
-
|
|
119
|
-
length: number
|
|
118
|
+
issuer: string | IIssuer
|
|
120
119
|
type: StatusListType
|
|
121
120
|
proofFormat: CredentialProofFormat
|
|
122
|
-
|
|
121
|
+
length: number
|
|
122
|
+
statusListCredential: StatusListCredential
|
|
123
123
|
statuslistContentType: string
|
|
124
|
-
issuer: string | IIssuer
|
|
125
|
-
statusList2021?: StatusList2021Details
|
|
126
|
-
oauthStatusList?: OAuthStatusDetails
|
|
127
|
-
bitstringStatusList?: BitstringStatusDetails
|
|
128
|
-
|
|
129
|
-
// These cannot be deduced from the VC, so they are present when callers pass in these values as params
|
|
130
124
|
correlationId?: string
|
|
131
125
|
driverType?: StatusListDriverType
|
|
132
|
-
credentialIdMode?: StatusListCredentialIdMode
|
|
133
|
-
}
|
|
134
126
|
|
|
135
|
-
|
|
136
|
-
indexingDirection
|
|
137
|
-
statusPurpose?: StatusPurpose2021
|
|
138
|
-
}
|
|
127
|
+
// Flattened StatusList2021 fields
|
|
128
|
+
indexingDirection?: StatusListIndexingDirection
|
|
129
|
+
statusPurpose?: StatusPurpose2021 | BitstringStatusPurpose | BitstringStatusPurpose[]
|
|
139
130
|
|
|
140
|
-
|
|
141
|
-
bitsPerStatus?:
|
|
131
|
+
// Flattened OAuth fields
|
|
132
|
+
bitsPerStatus?: number
|
|
142
133
|
expiresAt?: Date
|
|
143
|
-
}
|
|
144
134
|
|
|
145
|
-
|
|
146
|
-
statusPurpose: BitstringStatusPurpose
|
|
147
|
-
bitsPerStatus: number
|
|
135
|
+
// Flattened Bitstring fields
|
|
148
136
|
validFrom?: Date
|
|
149
137
|
validUntil?: Date
|
|
150
138
|
ttl?: number
|
|
139
|
+
|
|
140
|
+
// Legacy nested structures for backward compatibility
|
|
141
|
+
statusList2021?: {
|
|
142
|
+
indexingDirection: StatusListIndexingDirection
|
|
143
|
+
statusPurpose: StatusPurpose2021
|
|
144
|
+
}
|
|
145
|
+
oauthStatusList?: {
|
|
146
|
+
bitsPerStatus: number
|
|
147
|
+
expiresAt?: Date
|
|
148
|
+
}
|
|
149
|
+
bitstringStatusList?: {
|
|
150
|
+
statusPurpose: BitstringStatusPurpose | BitstringStatusPurpose[]
|
|
151
|
+
bitsPerStatus?: number
|
|
152
|
+
validFrom?: Date
|
|
153
|
+
validUntil?: Date
|
|
154
|
+
ttl?: number
|
|
155
|
+
}
|
|
151
156
|
}
|
|
152
157
|
|
|
153
158
|
export interface StatusList2021EntryCredentialStatus extends ICredentialStatus {
|