@sphereon/ssi-sdk.vc-status-list 0.34.1-next.7 → 0.34.1-next.85
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 +695 -122
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +163 -37
- package/dist/index.d.ts +163 -37
- package/dist/index.js +698 -125
- package/dist/index.js.map +1 -1
- package/package.json +10 -7
- package/src/functions.ts +126 -47
- package/src/impl/BitstringStatusListImplementation.ts +496 -0
- package/src/impl/IStatusList.ts +102 -8
- package/src/impl/OAuthStatusList.ts +133 -38
- package/src/impl/StatusList2021.ts +114 -34
- package/src/impl/StatusListFactory.ts +2 -0
- package/src/impl/encoding/cbor.ts +14 -12
- package/src/index.ts +1 -0
- package/src/types/BitstringStatusList.ts +4 -0
- package/src/types/index.ts +56 -35
- package/src/utils.ts +82 -20
package/dist/index.js
CHANGED
|
@@ -2,20 +2,20 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
3
|
|
|
4
4
|
// src/types/index.ts
|
|
5
|
-
var StatusOAuth = /* @__PURE__ */ function(StatusOAuth2) {
|
|
5
|
+
var StatusOAuth = /* @__PURE__ */ (function(StatusOAuth2) {
|
|
6
6
|
StatusOAuth2[StatusOAuth2["Valid"] = 0] = "Valid";
|
|
7
7
|
StatusOAuth2[StatusOAuth2["Invalid"] = 1] = "Invalid";
|
|
8
8
|
StatusOAuth2[StatusOAuth2["Suspended"] = 2] = "Suspended";
|
|
9
9
|
return StatusOAuth2;
|
|
10
|
-
}({});
|
|
11
|
-
var Status2021 = /* @__PURE__ */ function(Status20212) {
|
|
10
|
+
})({});
|
|
11
|
+
var Status2021 = /* @__PURE__ */ (function(Status20212) {
|
|
12
12
|
Status20212[Status20212["Valid"] = 0] = "Valid";
|
|
13
13
|
Status20212[Status20212["Invalid"] = 1] = "Invalid";
|
|
14
14
|
return Status20212;
|
|
15
|
-
}({});
|
|
15
|
+
})({});
|
|
16
16
|
|
|
17
17
|
// src/functions.ts
|
|
18
|
-
import { CredentialMapper as
|
|
18
|
+
import { CredentialMapper as CredentialMapper4, StatusListType as StatusListType6 } from "@sphereon/ssi-types";
|
|
19
19
|
import { checkStatus } from "@sphereon/vc-status-list";
|
|
20
20
|
|
|
21
21
|
// src/utils.ts
|
|
@@ -25,7 +25,8 @@ function getAssertedStatusListType(type) {
|
|
|
25
25
|
const assertedType = type ?? StatusListType.StatusList2021;
|
|
26
26
|
if (![
|
|
27
27
|
StatusListType.StatusList2021,
|
|
28
|
-
StatusListType.OAuthStatusList
|
|
28
|
+
StatusListType.OAuthStatusList,
|
|
29
|
+
StatusListType.BitstringStatusList
|
|
29
30
|
].includes(assertedType)) {
|
|
30
31
|
throw Error(`StatusList type ${assertedType} is not supported (yet)`);
|
|
31
32
|
}
|
|
@@ -62,8 +63,7 @@ var ValidProofTypeMap = /* @__PURE__ */ new Map([
|
|
|
62
63
|
StatusListType.StatusList2021,
|
|
63
64
|
[
|
|
64
65
|
"jwt",
|
|
65
|
-
"lds"
|
|
66
|
-
"EthereumEip712Signature2021"
|
|
66
|
+
"lds"
|
|
67
67
|
]
|
|
68
68
|
],
|
|
69
69
|
[
|
|
@@ -72,6 +72,13 @@ var ValidProofTypeMap = /* @__PURE__ */ new Map([
|
|
|
72
72
|
"jwt",
|
|
73
73
|
"cbor"
|
|
74
74
|
]
|
|
75
|
+
],
|
|
76
|
+
[
|
|
77
|
+
StatusListType.BitstringStatusList,
|
|
78
|
+
[
|
|
79
|
+
"lds",
|
|
80
|
+
"vc+jwt"
|
|
81
|
+
]
|
|
75
82
|
]
|
|
76
83
|
]);
|
|
77
84
|
function assertValidProofType(type, proofFormat) {
|
|
@@ -85,29 +92,50 @@ function determineStatusListType(credential) {
|
|
|
85
92
|
const proofFormat = determineProofFormat(credential);
|
|
86
93
|
switch (proofFormat) {
|
|
87
94
|
case "jwt":
|
|
88
|
-
|
|
89
|
-
const keys = Object.keys(payload);
|
|
90
|
-
if (keys.includes("status_list")) {
|
|
91
|
-
return StatusListType.OAuthStatusList;
|
|
92
|
-
} else if (keys.includes("vc")) {
|
|
93
|
-
return StatusListType.StatusList2021;
|
|
94
|
-
}
|
|
95
|
-
break;
|
|
95
|
+
return determineJwtStatusListType(credential);
|
|
96
96
|
case "lds":
|
|
97
|
-
|
|
98
|
-
const type = uniform.type.find((t) => {
|
|
99
|
-
return Object.values(StatusListType).some((statusType) => t.includes(statusType));
|
|
100
|
-
});
|
|
101
|
-
if (!type) {
|
|
102
|
-
throw new Error("Invalid status list credential type");
|
|
103
|
-
}
|
|
104
|
-
return type.replace("Credential", "");
|
|
97
|
+
return determineLdsStatusListType(credential);
|
|
105
98
|
case "cbor":
|
|
106
99
|
return StatusListType.OAuthStatusList;
|
|
100
|
+
default:
|
|
101
|
+
throw new Error("Cannot determine status list type from credential payload");
|
|
107
102
|
}
|
|
108
|
-
throw new Error("Cannot determine status list type from credential payload");
|
|
109
103
|
}
|
|
110
104
|
__name(determineStatusListType, "determineStatusListType");
|
|
105
|
+
function determineJwtStatusListType(credential) {
|
|
106
|
+
const payload = jwtDecode(credential);
|
|
107
|
+
if ("status_list" in payload) {
|
|
108
|
+
return StatusListType.OAuthStatusList;
|
|
109
|
+
}
|
|
110
|
+
if ("credentialSubject" in payload) {
|
|
111
|
+
return getStatusListTypeFromSubject(payload.credentialSubject);
|
|
112
|
+
}
|
|
113
|
+
if ("vc" in payload && "credentialSubject" in payload.vc) {
|
|
114
|
+
return getStatusListTypeFromSubject(payload.vc.credentialSubject);
|
|
115
|
+
}
|
|
116
|
+
throw new Error("Invalid status list credential: credentialSubject not found");
|
|
117
|
+
}
|
|
118
|
+
__name(determineJwtStatusListType, "determineJwtStatusListType");
|
|
119
|
+
function determineLdsStatusListType(credential) {
|
|
120
|
+
const uniform = CredentialMapper.toUniformCredential(credential);
|
|
121
|
+
const statusListType = uniform.type.find((type) => Object.values(StatusListType).some((statusType) => type.includes(statusType)));
|
|
122
|
+
if (!statusListType) {
|
|
123
|
+
throw new Error("Invalid status list credential type");
|
|
124
|
+
}
|
|
125
|
+
return statusListType.replace("Credential", "");
|
|
126
|
+
}
|
|
127
|
+
__name(determineLdsStatusListType, "determineLdsStatusListType");
|
|
128
|
+
function getStatusListTypeFromSubject(credentialSubject) {
|
|
129
|
+
switch (credentialSubject.type) {
|
|
130
|
+
case "StatusList2021":
|
|
131
|
+
return StatusListType.StatusList2021;
|
|
132
|
+
case "BitstringStatusList":
|
|
133
|
+
return StatusListType.BitstringStatusList;
|
|
134
|
+
default:
|
|
135
|
+
throw new Error(`Unknown credential subject type: ${credentialSubject.type}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
__name(getStatusListTypeFromSubject, "getStatusListTypeFromSubject");
|
|
111
139
|
function determineProofFormat(credential) {
|
|
112
140
|
const type = CredentialMapper.detectDocumentType(credential);
|
|
113
141
|
switch (type) {
|
|
@@ -122,6 +150,26 @@ function determineProofFormat(credential) {
|
|
|
122
150
|
}
|
|
123
151
|
}
|
|
124
152
|
__name(determineProofFormat, "determineProofFormat");
|
|
153
|
+
function ensureDate(value) {
|
|
154
|
+
if (value === void 0 || value === null) {
|
|
155
|
+
return void 0;
|
|
156
|
+
}
|
|
157
|
+
if (value instanceof Date) {
|
|
158
|
+
return value;
|
|
159
|
+
}
|
|
160
|
+
if (typeof value === "string") {
|
|
161
|
+
if (value.trim() === "") {
|
|
162
|
+
return void 0;
|
|
163
|
+
}
|
|
164
|
+
const date = new Date(value);
|
|
165
|
+
if (isNaN(date.getTime())) {
|
|
166
|
+
return void 0;
|
|
167
|
+
}
|
|
168
|
+
return date;
|
|
169
|
+
}
|
|
170
|
+
return void 0;
|
|
171
|
+
}
|
|
172
|
+
__name(ensureDate, "ensureDate");
|
|
125
173
|
|
|
126
174
|
// src/impl/StatusList2021.ts
|
|
127
175
|
import { CredentialMapper as CredentialMapper2, DocumentFormat as DocumentFormat2, StatusListType as StatusListType2 } from "@sphereon/ssi-types";
|
|
@@ -185,13 +233,14 @@ var StatusList2021Implementation = class {
|
|
|
185
233
|
encodedList,
|
|
186
234
|
proofFormat
|
|
187
235
|
}, context);
|
|
236
|
+
if (!("statusPurpose" in credentialSubject)) {
|
|
237
|
+
return Promise.reject(Error("statusPurpose is required in credentialSubject for StatusList2021"));
|
|
238
|
+
}
|
|
188
239
|
return {
|
|
189
240
|
statusListCredential: updatedCredential,
|
|
190
241
|
encodedList,
|
|
191
242
|
statusList2021: {
|
|
192
|
-
|
|
193
|
-
statusPurpose: credentialSubject.statusPurpose
|
|
194
|
-
} : {},
|
|
243
|
+
statusPurpose: credentialSubject.statusPurpose,
|
|
195
244
|
indexingDirection: "rightToLeft"
|
|
196
245
|
},
|
|
197
246
|
length: statusList.length - 1,
|
|
@@ -214,7 +263,7 @@ var StatusList2021Implementation = class {
|
|
|
214
263
|
encodedList: args.encodedList
|
|
215
264
|
});
|
|
216
265
|
const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
|
|
217
|
-
statusList.setStatus(index, args.value);
|
|
266
|
+
statusList.setStatus(index, args.value !== 0);
|
|
218
267
|
const newEncodedList = await statusList.encode();
|
|
219
268
|
const credential = await this.createVerifiableCredential({
|
|
220
269
|
id,
|
|
@@ -248,36 +297,88 @@ var StatusList2021Implementation = class {
|
|
|
248
297
|
const status = statusList.getStatus(typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex));
|
|
249
298
|
return status ? Status2021.Invalid : Status2021.Valid;
|
|
250
299
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
300
|
+
/**
|
|
301
|
+
* Performs the initial parsing of a StatusListCredential.
|
|
302
|
+
* This method handles expensive operations like JWT/CWT decoding once.
|
|
303
|
+
* It extracts all details available from the credential payload itself.
|
|
304
|
+
*/
|
|
305
|
+
async extractCredentialDetails(credential) {
|
|
306
|
+
const uniform = CredentialMapper2.toUniformCredential(credential);
|
|
254
307
|
const { issuer, credentialSubject } = uniform;
|
|
255
|
-
const
|
|
256
|
-
const encodedList = getAssertedProperty("encodedList", credentialSubject);
|
|
257
|
-
const proofFormat = CredentialMapper2.detectDocumentType(statusListPayload) === DocumentFormat2.JWT ? "jwt" : "lds";
|
|
258
|
-
const statusPurpose = getAssertedProperty("statusPurpose", credentialSubject);
|
|
259
|
-
const list = await StatusList.decode({
|
|
260
|
-
encodedList
|
|
261
|
-
});
|
|
308
|
+
const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
262
309
|
return {
|
|
263
|
-
id,
|
|
264
|
-
encodedList,
|
|
310
|
+
id: getAssertedValue("id", uniform.id),
|
|
265
311
|
issuer,
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
312
|
+
encodedList: getAssertedProperty("encodedList", subject)
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
async toStatusListDetails(args) {
|
|
316
|
+
if ("statusListCredential" in args) {
|
|
317
|
+
const { statusListCredential, correlationId, driverType } = args;
|
|
318
|
+
const uniform = CredentialMapper2.toUniformCredential(statusListCredential);
|
|
319
|
+
const { issuer, credentialSubject } = uniform;
|
|
320
|
+
const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
321
|
+
const id = getAssertedValue("id", uniform.id);
|
|
322
|
+
const encodedList = getAssertedProperty("encodedList", subject);
|
|
323
|
+
const statusPurpose = getAssertedProperty("statusPurpose", subject);
|
|
324
|
+
const proofFormat = CredentialMapper2.detectDocumentType(statusListCredential) === DocumentFormat2.JWT ? "jwt" : "lds";
|
|
325
|
+
const list = await StatusList.decode({
|
|
326
|
+
encodedList
|
|
327
|
+
});
|
|
328
|
+
return {
|
|
329
|
+
id,
|
|
330
|
+
encodedList,
|
|
331
|
+
issuer,
|
|
332
|
+
type: StatusListType2.StatusList2021,
|
|
333
|
+
proofFormat,
|
|
334
|
+
length: list.length,
|
|
335
|
+
statusListCredential,
|
|
336
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
337
|
+
correlationId,
|
|
338
|
+
driverType,
|
|
272
339
|
indexingDirection: "rightToLeft",
|
|
273
|
-
statusPurpose
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
340
|
+
statusPurpose,
|
|
341
|
+
statusList2021: {
|
|
342
|
+
indexingDirection: "rightToLeft",
|
|
343
|
+
statusPurpose
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
} else {
|
|
347
|
+
const { extractedDetails, statusListEntity } = args;
|
|
348
|
+
const statusList2021Entity = statusListEntity;
|
|
349
|
+
const proofFormat = CredentialMapper2.detectDocumentType(statusListEntity.statusListCredential) === DocumentFormat2.JWT ? "jwt" : "lds";
|
|
350
|
+
const list = await StatusList.decode({
|
|
351
|
+
encodedList: extractedDetails.encodedList
|
|
352
|
+
});
|
|
353
|
+
return {
|
|
354
|
+
id: extractedDetails.id,
|
|
355
|
+
encodedList: extractedDetails.encodedList,
|
|
356
|
+
issuer: extractedDetails.issuer,
|
|
357
|
+
type: StatusListType2.StatusList2021,
|
|
358
|
+
proofFormat,
|
|
359
|
+
length: list.length,
|
|
360
|
+
statusListCredential: statusListEntity.statusListCredential,
|
|
361
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
362
|
+
correlationId: statusListEntity.correlationId,
|
|
363
|
+
driverType: statusListEntity.driverType,
|
|
364
|
+
indexingDirection: statusList2021Entity.indexingDirection,
|
|
365
|
+
statusPurpose: statusList2021Entity.statusPurpose,
|
|
366
|
+
statusList2021: {
|
|
367
|
+
indexingDirection: statusList2021Entity.indexingDirection,
|
|
368
|
+
statusPurpose: statusList2021Entity.statusPurpose
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
async createCredentialStatus(args) {
|
|
374
|
+
const { statusList, statusListIndex } = args;
|
|
375
|
+
const statusList2021 = statusList;
|
|
376
|
+
return {
|
|
377
|
+
id: `${statusList.id}#${statusListIndex}`,
|
|
378
|
+
type: "StatusList2021Entry",
|
|
379
|
+
statusPurpose: statusList2021.statusPurpose ?? "revocation",
|
|
380
|
+
statusListIndex: "" + statusListIndex,
|
|
381
|
+
statusListCredential: statusList.id
|
|
281
382
|
};
|
|
282
383
|
}
|
|
283
384
|
async createVerifiableCredential(args, context) {
|
|
@@ -413,12 +514,12 @@ var getSigningAlgo = /* @__PURE__ */ __name((type) => {
|
|
|
413
514
|
// src/impl/encoding/cbor.ts
|
|
414
515
|
import { StatusList as StatusList3 } from "@sd-jwt/jwt-status-list";
|
|
415
516
|
import { deflate, inflate } from "pako";
|
|
416
|
-
import
|
|
517
|
+
import mdocPkg from "@sphereon/kmp-mdoc-core";
|
|
417
518
|
import base64url2 from "base64url";
|
|
418
|
-
var { com, kotlin } =
|
|
419
|
-
var CborByteString = com.sphereon.cbor.CborByteString;
|
|
420
|
-
var CborUInt = com.sphereon.cbor.CborUInt;
|
|
421
|
-
var CborString = com.sphereon.cbor.CborString;
|
|
519
|
+
var { com, kotlin } = mdocPkg;
|
|
520
|
+
var CborByteString = mdocPkg.com.sphereon.cbor.CborByteString;
|
|
521
|
+
var CborUInt = mdocPkg.com.sphereon.cbor.CborUInt;
|
|
522
|
+
var CborString = mdocPkg.com.sphereon.cbor.CborString;
|
|
422
523
|
var decompressRawStatusList = StatusList3.decodeStatusList.bind(StatusList3);
|
|
423
524
|
var CWT_CLAIMS = {
|
|
424
525
|
SUBJECT: 2,
|
|
@@ -572,7 +673,8 @@ var OAuthStatusListImplementation = class {
|
|
|
572
673
|
}
|
|
573
674
|
const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT2;
|
|
574
675
|
const { issuer, id, oauthStatusList, keyRef } = args;
|
|
575
|
-
const { bitsPerStatus
|
|
676
|
+
const { bitsPerStatus } = oauthStatusList;
|
|
677
|
+
const expiresAt = ensureDate(oauthStatusList.expiresAt);
|
|
576
678
|
const length = args.length ?? DEFAULT_LIST_LENGTH2;
|
|
577
679
|
const issuerString = typeof issuer === "string" ? issuer : issuer.id;
|
|
578
680
|
const correlationId = getAssertedValue("correlationId", args.correlationId);
|
|
@@ -595,7 +697,8 @@ var OAuthStatusListImplementation = class {
|
|
|
595
697
|
};
|
|
596
698
|
}
|
|
597
699
|
async updateStatusListIndex(args, context) {
|
|
598
|
-
const { statusListCredential, value,
|
|
700
|
+
const { statusListCredential, value, keyRef } = args;
|
|
701
|
+
const expiresAt = ensureDate(args.expiresAt);
|
|
599
702
|
if (typeof statusListCredential !== "string") {
|
|
600
703
|
return Promise.reject("statusListCredential in neither JWT nor CWT");
|
|
601
704
|
}
|
|
@@ -606,6 +709,9 @@ var OAuthStatusListImplementation = class {
|
|
|
606
709
|
if (index < 0 || index >= statusList.statusList.length) {
|
|
607
710
|
throw new Error("Status list index out of bounds");
|
|
608
711
|
}
|
|
712
|
+
if (typeof value !== "number") {
|
|
713
|
+
throw new Error("Status list values should be of type number");
|
|
714
|
+
}
|
|
609
715
|
statusList.setStatus(index, value);
|
|
610
716
|
const { statusListCredential: signedCredential, encodedList } = await this.createSignedStatusList(proofFormat, context, statusList, issuer, id, expiresAt, keyRef);
|
|
611
717
|
return {
|
|
@@ -628,12 +734,13 @@ var OAuthStatusListImplementation = class {
|
|
|
628
734
|
throw new Error("OAuthStatusList options are required for type OAuthStatusList");
|
|
629
735
|
}
|
|
630
736
|
const { proofFormat, oauthStatusList, keyRef } = args;
|
|
631
|
-
const { bitsPerStatus
|
|
737
|
+
const { bitsPerStatus } = oauthStatusList;
|
|
738
|
+
const expiresAt = ensureDate(oauthStatusList.expiresAt);
|
|
632
739
|
const { issuer, id } = getAssertedValues(args);
|
|
633
740
|
const issuerString = typeof issuer === "string" ? issuer : issuer.id;
|
|
634
741
|
const listToUpdate = StatusList4.decompressStatusList(args.encodedList, bitsPerStatus ?? DEFAULT_BITS_PER_STATUS);
|
|
635
742
|
const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
|
|
636
|
-
listToUpdate.setStatus(index, args.value
|
|
743
|
+
listToUpdate.setStatus(index, args.value);
|
|
637
744
|
const { statusListCredential, encodedList } = await this.createSignedStatusList(proofFormat ?? DEFAULT_PROOF_FORMAT2, context, listToUpdate, issuerString, id, expiresAt, keyRef);
|
|
638
745
|
return {
|
|
639
746
|
encodedList,
|
|
@@ -650,9 +757,6 @@ var OAuthStatusListImplementation = class {
|
|
|
650
757
|
statuslistContentType: this.buildContentType(proofFormat)
|
|
651
758
|
};
|
|
652
759
|
}
|
|
653
|
-
buildContentType(proofFormat) {
|
|
654
|
-
return `application/statuslist+${proofFormat === "cbor" ? "cwt" : "jwt"}`;
|
|
655
|
-
}
|
|
656
760
|
async checkStatusIndex(args) {
|
|
657
761
|
const { statusListCredential, statusListIndex } = args;
|
|
658
762
|
if (typeof statusListCredential !== "string") {
|
|
@@ -662,38 +766,105 @@ var OAuthStatusListImplementation = class {
|
|
|
662
766
|
const { statusList } = proofFormat === "jwt" ? decodeStatusListJWT(statusListCredential) : decodeStatusListCWT(statusListCredential);
|
|
663
767
|
const index = typeof statusListIndex === "number" ? statusListIndex : parseInt(statusListIndex);
|
|
664
768
|
if (index < 0 || index >= statusList.statusList.length) {
|
|
665
|
-
throw new Error(
|
|
769
|
+
throw new Error(`Status list index out of bounds, has ${statusList.statusList.length} items, requested ${index}`);
|
|
666
770
|
}
|
|
667
771
|
return statusList.getStatus(index);
|
|
668
772
|
}
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
773
|
+
/**
|
|
774
|
+
* Performs the initial parsing of a StatusListCredential.
|
|
775
|
+
* This method handles expensive operations like JWT/CWT decoding once.
|
|
776
|
+
* It extracts all details available from the credential payload itself.
|
|
777
|
+
*/
|
|
778
|
+
async extractCredentialDetails(credential) {
|
|
779
|
+
if (typeof credential !== "string") {
|
|
780
|
+
return Promise.reject("statusListCredential must be a JWT or CWT string");
|
|
781
|
+
}
|
|
782
|
+
const proofFormat = determineProofFormat(credential);
|
|
783
|
+
const decoded = proofFormat === "jwt" ? decodeStatusListJWT(credential) : decodeStatusListCWT(credential);
|
|
674
784
|
return {
|
|
675
|
-
id,
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
expiresAt: new Date(exp * 1e3)
|
|
687
|
-
}
|
|
688
|
-
},
|
|
689
|
-
...args.correlationId && {
|
|
690
|
-
correlationId: args.correlationId
|
|
691
|
-
},
|
|
692
|
-
...args.driverType && {
|
|
693
|
-
driverType: args.driverType
|
|
785
|
+
id: decoded.id,
|
|
786
|
+
issuer: decoded.issuer,
|
|
787
|
+
encodedList: decoded.statusList.compressStatusList(),
|
|
788
|
+
decodedPayload: decoded
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
async toStatusListDetails(args) {
|
|
792
|
+
if ("statusListCredential" in args) {
|
|
793
|
+
const { statusListCredential, bitsPerStatus, correlationId, driverType } = args;
|
|
794
|
+
if (!bitsPerStatus || bitsPerStatus < 1) {
|
|
795
|
+
return Promise.reject(Error("bitsPerStatus must be set for OAuth status lists and must be 1 or higher"));
|
|
694
796
|
}
|
|
797
|
+
const proofFormat = determineProofFormat(statusListCredential);
|
|
798
|
+
const decoded = proofFormat === "jwt" ? decodeStatusListJWT(statusListCredential) : decodeStatusListCWT(statusListCredential);
|
|
799
|
+
const { statusList, issuer, id, exp } = decoded;
|
|
800
|
+
const expiresAt = exp ? new Date(exp * 1e3) : void 0;
|
|
801
|
+
return {
|
|
802
|
+
id,
|
|
803
|
+
encodedList: statusList.compressStatusList(),
|
|
804
|
+
issuer,
|
|
805
|
+
type: StatusListType3.OAuthStatusList,
|
|
806
|
+
proofFormat,
|
|
807
|
+
length: statusList.statusList.length,
|
|
808
|
+
statusListCredential,
|
|
809
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
810
|
+
correlationId,
|
|
811
|
+
driverType,
|
|
812
|
+
bitsPerStatus,
|
|
813
|
+
...expiresAt && {
|
|
814
|
+
expiresAt
|
|
815
|
+
},
|
|
816
|
+
oauthStatusList: {
|
|
817
|
+
bitsPerStatus,
|
|
818
|
+
...expiresAt && {
|
|
819
|
+
expiresAt
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
} else {
|
|
824
|
+
const { extractedDetails, statusListEntity } = args;
|
|
825
|
+
const oauthEntity = statusListEntity;
|
|
826
|
+
const decoded = extractedDetails.decodedPayload;
|
|
827
|
+
const proofFormat = determineProofFormat(statusListEntity.statusListCredential);
|
|
828
|
+
const expiresAt = decoded.exp ? new Date(decoded.exp * 1e3) : void 0;
|
|
829
|
+
return {
|
|
830
|
+
id: extractedDetails.id,
|
|
831
|
+
encodedList: extractedDetails.encodedList,
|
|
832
|
+
issuer: extractedDetails.issuer,
|
|
833
|
+
type: StatusListType3.OAuthStatusList,
|
|
834
|
+
proofFormat,
|
|
835
|
+
length: decoded.statusList.statusList.length,
|
|
836
|
+
statusListCredential: statusListEntity.statusListCredential,
|
|
837
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
838
|
+
correlationId: statusListEntity.correlationId,
|
|
839
|
+
driverType: statusListEntity.driverType,
|
|
840
|
+
bitsPerStatus: oauthEntity.bitsPerStatus,
|
|
841
|
+
...expiresAt && {
|
|
842
|
+
expiresAt
|
|
843
|
+
},
|
|
844
|
+
oauthStatusList: {
|
|
845
|
+
bitsPerStatus: oauthEntity.bitsPerStatus,
|
|
846
|
+
...expiresAt && {
|
|
847
|
+
expiresAt
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
async createCredentialStatus(args) {
|
|
854
|
+
const { statusList, statusListIndex } = args;
|
|
855
|
+
const oauthStatusList = statusList;
|
|
856
|
+
return {
|
|
857
|
+
id: `${statusList.id}#${statusListIndex}`,
|
|
858
|
+
type: "OAuthStatusListEntry",
|
|
859
|
+
bitsPerStatus: oauthStatusList.bitsPerStatus,
|
|
860
|
+
statusListIndex: "" + statusListIndex,
|
|
861
|
+
statusListCredential: statusList.id,
|
|
862
|
+
expiresAt: oauthStatusList.expiresAt
|
|
695
863
|
};
|
|
696
864
|
}
|
|
865
|
+
buildContentType(proofFormat) {
|
|
866
|
+
return `application/statuslist+${proofFormat === "cbor" ? "cwt" : "jwt"}`;
|
|
867
|
+
}
|
|
697
868
|
async createSignedStatusList(proofFormat, context, statusList, issuerString, id, expiresAt, keyRef) {
|
|
698
869
|
switch (proofFormat) {
|
|
699
870
|
case "jwt": {
|
|
@@ -709,7 +880,405 @@ var OAuthStatusListImplementation = class {
|
|
|
709
880
|
};
|
|
710
881
|
|
|
711
882
|
// src/impl/StatusListFactory.ts
|
|
712
|
-
import { StatusListType as
|
|
883
|
+
import { StatusListType as StatusListType5 } from "@sphereon/ssi-types";
|
|
884
|
+
|
|
885
|
+
// src/impl/BitstringStatusListImplementation.ts
|
|
886
|
+
import { CredentialMapper as CredentialMapper3, DocumentFormat as DocumentFormat3, StatusListType as StatusListType4 } from "@sphereon/ssi-types";
|
|
887
|
+
import { BitstreamStatusList, createStatusListCredential } from "@4sure-tech/vc-bitstring-status-lists";
|
|
888
|
+
var DEFAULT_LIST_LENGTH3 = 131072;
|
|
889
|
+
var DEFAULT_PROOF_FORMAT3 = "vc+jwt";
|
|
890
|
+
var DEFAULT_STATUS_PURPOSE = "revocation";
|
|
891
|
+
var BitstringStatusListImplementation = class {
|
|
892
|
+
static {
|
|
893
|
+
__name(this, "BitstringStatusListImplementation");
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Creates a new bitstring status list with the specified configuration
|
|
897
|
+
*
|
|
898
|
+
* @param args - Configuration for the new status list including issuer, purpose, and size
|
|
899
|
+
* @param context - Veramo agent context for credential operations
|
|
900
|
+
* @returns Promise resolving to the created status list details
|
|
901
|
+
*/
|
|
902
|
+
async createNewStatusList(args, context) {
|
|
903
|
+
if (!args.bitstringStatusList) {
|
|
904
|
+
throw new Error("BitstringStatusList options are required for type BitstringStatusList");
|
|
905
|
+
}
|
|
906
|
+
const length = args?.length ?? DEFAULT_LIST_LENGTH3;
|
|
907
|
+
const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT3;
|
|
908
|
+
assertValidProofType(StatusListType4.BitstringStatusList, proofFormat);
|
|
909
|
+
const { issuer, id } = args;
|
|
910
|
+
const correlationId = getAssertedValue("correlationId", args.correlationId);
|
|
911
|
+
const { statusPurpose, bitsPerStatus, validFrom, validUntil, ttl } = args.bitstringStatusList;
|
|
912
|
+
const unsignedCredential = await createStatusListCredential({
|
|
913
|
+
id,
|
|
914
|
+
issuer,
|
|
915
|
+
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
916
|
+
validFrom: ensureDate(validFrom),
|
|
917
|
+
validUntil: ensureDate(validUntil),
|
|
918
|
+
ttl
|
|
919
|
+
});
|
|
920
|
+
const statusListCredential = await this.createVerifiableCredential({
|
|
921
|
+
unsignedCredential,
|
|
922
|
+
id,
|
|
923
|
+
issuer,
|
|
924
|
+
proofFormat,
|
|
925
|
+
keyRef: args.keyRef
|
|
926
|
+
}, context);
|
|
927
|
+
return {
|
|
928
|
+
encodedList: unsignedCredential.credentialSubject.encodedList,
|
|
929
|
+
statusListCredential,
|
|
930
|
+
bitstringStatusList: {
|
|
931
|
+
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
932
|
+
...unsignedCredential.validFrom && {
|
|
933
|
+
validFrom: new Date(unsignedCredential.validFrom)
|
|
934
|
+
},
|
|
935
|
+
...unsignedCredential.validUntil && {
|
|
936
|
+
validUntil: new Date(unsignedCredential.validUntil)
|
|
937
|
+
},
|
|
938
|
+
ttl,
|
|
939
|
+
bitsPerStatus
|
|
940
|
+
},
|
|
941
|
+
length,
|
|
942
|
+
type: StatusListType4.BitstringStatusList,
|
|
943
|
+
proofFormat,
|
|
944
|
+
id,
|
|
945
|
+
correlationId,
|
|
946
|
+
issuer,
|
|
947
|
+
statuslistContentType: this.buildContentType(proofFormat)
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* Updates the status of a specific credential in an existing status list
|
|
952
|
+
*
|
|
953
|
+
* @param args - Update parameters including the status list credential, index, and new value
|
|
954
|
+
* @param context - Veramo agent context for credential operations
|
|
955
|
+
* @returns Promise resolving to the updated status list details
|
|
956
|
+
*/
|
|
957
|
+
async updateStatusListIndex(args, context) {
|
|
958
|
+
if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
|
|
959
|
+
return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListIndex)"));
|
|
960
|
+
}
|
|
961
|
+
const credential = args.statusListCredential;
|
|
962
|
+
const uniform = CredentialMapper3.toUniformCredential(credential);
|
|
963
|
+
const { issuer, credentialSubject } = uniform;
|
|
964
|
+
const id = getAssertedValue("id", uniform.id);
|
|
965
|
+
const origEncodedList = getAssertedProperty("encodedList", credentialSubject);
|
|
966
|
+
const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
|
|
967
|
+
const statusList = await BitstreamStatusList.decode({
|
|
968
|
+
encodedList: origEncodedList,
|
|
969
|
+
statusSize: args.bitsPerStatus
|
|
970
|
+
});
|
|
971
|
+
const bitstringStatusId = args.value;
|
|
972
|
+
statusList.setStatus(index, bitstringStatusId);
|
|
973
|
+
const proofFormat = CredentialMapper3.detectDocumentType(credential) === DocumentFormat3.JWT ? "vc+jwt" : "lds";
|
|
974
|
+
const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
975
|
+
const statusPurpose = getAssertedProperty("statusPurpose", credSubject);
|
|
976
|
+
const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : void 0;
|
|
977
|
+
const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : void 0;
|
|
978
|
+
const ttl = credSubject.ttl;
|
|
979
|
+
const unsignedCredential = await createStatusListCredential({
|
|
980
|
+
id,
|
|
981
|
+
issuer,
|
|
982
|
+
statusList,
|
|
983
|
+
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
984
|
+
validFrom: ensureDate(validFrom),
|
|
985
|
+
validUntil: ensureDate(validUntil),
|
|
986
|
+
ttl
|
|
987
|
+
});
|
|
988
|
+
const updatedCredential = await this.createVerifiableCredential({
|
|
989
|
+
unsignedCredential,
|
|
990
|
+
id,
|
|
991
|
+
issuer,
|
|
992
|
+
proofFormat,
|
|
993
|
+
keyRef: args.keyRef
|
|
994
|
+
}, context);
|
|
995
|
+
return {
|
|
996
|
+
statusListCredential: updatedCredential,
|
|
997
|
+
encodedList: unsignedCredential.credentialSubject.encodedList,
|
|
998
|
+
bitstringStatusList: {
|
|
999
|
+
statusPurpose,
|
|
1000
|
+
...unsignedCredential.validFrom && {
|
|
1001
|
+
validFrom: new Date(unsignedCredential.validFrom)
|
|
1002
|
+
},
|
|
1003
|
+
...unsignedCredential.validUntil && {
|
|
1004
|
+
validUntil: new Date(unsignedCredential.validUntil)
|
|
1005
|
+
},
|
|
1006
|
+
bitsPerStatus: args.bitsPerStatus,
|
|
1007
|
+
ttl
|
|
1008
|
+
},
|
|
1009
|
+
length: statusList.getLength(),
|
|
1010
|
+
type: StatusListType4.BitstringStatusList,
|
|
1011
|
+
proofFormat,
|
|
1012
|
+
id,
|
|
1013
|
+
issuer,
|
|
1014
|
+
statuslistContentType: this.buildContentType(proofFormat)
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
/**
|
|
1018
|
+
* Updates a status list by decoding an encoded list, modifying it, and re-encoding
|
|
1019
|
+
*
|
|
1020
|
+
* @param args - Update parameters including encoded list, index, and new value
|
|
1021
|
+
* @param context - Veramo agent context for credential operations
|
|
1022
|
+
* @returns Promise resolving to the updated status list details
|
|
1023
|
+
*/
|
|
1024
|
+
async updateStatusListFromEncodedList(args, context) {
|
|
1025
|
+
if (!args.bitstringStatusList) {
|
|
1026
|
+
throw new Error("bitstringStatusList options required for type BitstringStatusList");
|
|
1027
|
+
}
|
|
1028
|
+
if (args.bitstringStatusList.bitsPerStatus < 1) {
|
|
1029
|
+
return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListFromEncodedList)"));
|
|
1030
|
+
}
|
|
1031
|
+
const { statusPurpose, bitsPerStatus, ttl, validFrom, validUntil } = args.bitstringStatusList;
|
|
1032
|
+
const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT3;
|
|
1033
|
+
assertValidProofType(StatusListType4.BitstringStatusList, proofFormat);
|
|
1034
|
+
const { issuer, id } = getAssertedValues(args);
|
|
1035
|
+
const statusList = await BitstreamStatusList.decode({
|
|
1036
|
+
encodedList: args.encodedList,
|
|
1037
|
+
statusSize: bitsPerStatus
|
|
1038
|
+
});
|
|
1039
|
+
const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
|
|
1040
|
+
statusList.setStatus(index, args.value);
|
|
1041
|
+
const unsignedCredential = await createStatusListCredential({
|
|
1042
|
+
id,
|
|
1043
|
+
issuer,
|
|
1044
|
+
statusList,
|
|
1045
|
+
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
1046
|
+
validFrom: ensureDate(validFrom),
|
|
1047
|
+
validUntil: ensureDate(validUntil),
|
|
1048
|
+
ttl
|
|
1049
|
+
});
|
|
1050
|
+
const credential = await this.createVerifiableCredential({
|
|
1051
|
+
unsignedCredential,
|
|
1052
|
+
id,
|
|
1053
|
+
issuer,
|
|
1054
|
+
proofFormat,
|
|
1055
|
+
keyRef: args.keyRef
|
|
1056
|
+
}, context);
|
|
1057
|
+
return {
|
|
1058
|
+
type: StatusListType4.BitstringStatusList,
|
|
1059
|
+
statusListCredential: credential,
|
|
1060
|
+
encodedList: unsignedCredential.credentialSubject.encodedList,
|
|
1061
|
+
bitstringStatusList: {
|
|
1062
|
+
statusPurpose,
|
|
1063
|
+
bitsPerStatus,
|
|
1064
|
+
...unsignedCredential.validFrom && {
|
|
1065
|
+
validFrom: new Date(unsignedCredential.validFrom)
|
|
1066
|
+
},
|
|
1067
|
+
...unsignedCredential.validUntil && {
|
|
1068
|
+
validUntil: new Date(unsignedCredential.validUntil)
|
|
1069
|
+
},
|
|
1070
|
+
ttl
|
|
1071
|
+
},
|
|
1072
|
+
length: statusList.getLength(),
|
|
1073
|
+
proofFormat: args.proofFormat ?? "lds",
|
|
1074
|
+
id,
|
|
1075
|
+
issuer,
|
|
1076
|
+
statuslistContentType: this.buildContentType(proofFormat)
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* Checks the status of a specific credential by its index in the status list
|
|
1081
|
+
*
|
|
1082
|
+
* @param args - Check parameters including the status list credential and index
|
|
1083
|
+
* @returns Promise resolving to the status value at the specified index
|
|
1084
|
+
*/
|
|
1085
|
+
async checkStatusIndex(args) {
|
|
1086
|
+
if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
|
|
1087
|
+
return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (checkStatusIndex)"));
|
|
1088
|
+
}
|
|
1089
|
+
const uniform = CredentialMapper3.toUniformCredential(args.statusListCredential);
|
|
1090
|
+
const { credentialSubject } = uniform;
|
|
1091
|
+
const encodedList = getAssertedProperty("encodedList", credentialSubject);
|
|
1092
|
+
const statusList = await BitstreamStatusList.decode({
|
|
1093
|
+
encodedList,
|
|
1094
|
+
statusSize: args.bitsPerStatus
|
|
1095
|
+
});
|
|
1096
|
+
const numIndex = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
|
|
1097
|
+
if (statusList.getLength() <= numIndex) {
|
|
1098
|
+
throw new Error(`Status list index out of bounds, has ${statusList.getLength()} entries, requested ${numIndex}`);
|
|
1099
|
+
}
|
|
1100
|
+
return statusList.getStatus(numIndex);
|
|
1101
|
+
}
|
|
1102
|
+
/**
|
|
1103
|
+
* Performs the initial parsing of a StatusListCredential.
|
|
1104
|
+
* This method handles expensive operations like JWT/CWT decoding once.
|
|
1105
|
+
* It extracts all details available from the credential payload itself.
|
|
1106
|
+
*/
|
|
1107
|
+
async extractCredentialDetails(credential) {
|
|
1108
|
+
const uniform = CredentialMapper3.toUniformCredential(credential);
|
|
1109
|
+
const { issuer, credentialSubject } = uniform;
|
|
1110
|
+
const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
1111
|
+
return {
|
|
1112
|
+
id: getAssertedValue("id", uniform.id),
|
|
1113
|
+
issuer,
|
|
1114
|
+
encodedList: getAssertedProperty("encodedList", subject)
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
async toStatusListDetails(args) {
|
|
1118
|
+
if ("statusListCredential" in args) {
|
|
1119
|
+
const { statusListCredential, bitsPerStatus, correlationId, driverType } = args;
|
|
1120
|
+
if (!bitsPerStatus || bitsPerStatus < 1) {
|
|
1121
|
+
return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher"));
|
|
1122
|
+
}
|
|
1123
|
+
const uniform = CredentialMapper3.toUniformCredential(statusListCredential);
|
|
1124
|
+
const { issuer, credentialSubject } = uniform;
|
|
1125
|
+
const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
1126
|
+
const id = getAssertedValue("id", uniform.id);
|
|
1127
|
+
const encodedList = getAssertedProperty("encodedList", subject);
|
|
1128
|
+
const statusPurpose = getAssertedProperty("statusPurpose", subject);
|
|
1129
|
+
const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : void 0;
|
|
1130
|
+
const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : void 0;
|
|
1131
|
+
const ttl = subject.ttl;
|
|
1132
|
+
const proofFormat = CredentialMapper3.detectDocumentType(statusListCredential) === DocumentFormat3.JWT ? "vc+jwt" : "lds";
|
|
1133
|
+
const statuslistLength = BitstreamStatusList.getStatusListLength(encodedList, bitsPerStatus);
|
|
1134
|
+
return {
|
|
1135
|
+
id,
|
|
1136
|
+
encodedList,
|
|
1137
|
+
issuer,
|
|
1138
|
+
type: StatusListType4.BitstringStatusList,
|
|
1139
|
+
proofFormat,
|
|
1140
|
+
length: statuslistLength,
|
|
1141
|
+
statusListCredential,
|
|
1142
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
1143
|
+
correlationId,
|
|
1144
|
+
driverType,
|
|
1145
|
+
statusPurpose,
|
|
1146
|
+
bitsPerStatus,
|
|
1147
|
+
...validFrom && {
|
|
1148
|
+
validFrom
|
|
1149
|
+
},
|
|
1150
|
+
...validUntil && {
|
|
1151
|
+
validUntil
|
|
1152
|
+
},
|
|
1153
|
+
...ttl && {
|
|
1154
|
+
ttl
|
|
1155
|
+
},
|
|
1156
|
+
bitstringStatusList: {
|
|
1157
|
+
statusPurpose,
|
|
1158
|
+
bitsPerStatus,
|
|
1159
|
+
...validFrom && {
|
|
1160
|
+
validFrom
|
|
1161
|
+
},
|
|
1162
|
+
...validUntil && {
|
|
1163
|
+
validUntil
|
|
1164
|
+
},
|
|
1165
|
+
...ttl && {
|
|
1166
|
+
ttl
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
};
|
|
1170
|
+
} else {
|
|
1171
|
+
const { extractedDetails, statusListEntity } = args;
|
|
1172
|
+
const bitstringEntity = statusListEntity;
|
|
1173
|
+
if (!bitstringEntity.bitsPerStatus) {
|
|
1174
|
+
return Promise.reject(Error("bitsPerStatus must be present for a bitstring status list"));
|
|
1175
|
+
}
|
|
1176
|
+
const proofFormat = CredentialMapper3.detectDocumentType(statusListEntity.statusListCredential) === DocumentFormat3.JWT ? "vc+jwt" : "lds";
|
|
1177
|
+
const statuslistLength = BitstreamStatusList.getStatusListLength(extractedDetails.encodedList, bitstringEntity.bitsPerStatus);
|
|
1178
|
+
return {
|
|
1179
|
+
id: extractedDetails.id,
|
|
1180
|
+
encodedList: extractedDetails.encodedList,
|
|
1181
|
+
issuer: extractedDetails.issuer,
|
|
1182
|
+
type: StatusListType4.BitstringStatusList,
|
|
1183
|
+
proofFormat,
|
|
1184
|
+
length: statuslistLength,
|
|
1185
|
+
statusListCredential: statusListEntity.statusListCredential,
|
|
1186
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
1187
|
+
correlationId: statusListEntity.correlationId,
|
|
1188
|
+
driverType: statusListEntity.driverType,
|
|
1189
|
+
statusPurpose: bitstringEntity.statusPurpose,
|
|
1190
|
+
bitsPerStatus: bitstringEntity.bitsPerStatus,
|
|
1191
|
+
...bitstringEntity.validFrom && {
|
|
1192
|
+
validFrom: bitstringEntity.validFrom
|
|
1193
|
+
},
|
|
1194
|
+
...bitstringEntity.validUntil && {
|
|
1195
|
+
validUntil: bitstringEntity.validUntil
|
|
1196
|
+
},
|
|
1197
|
+
...bitstringEntity.ttl && {
|
|
1198
|
+
ttl: bitstringEntity.ttl
|
|
1199
|
+
},
|
|
1200
|
+
bitstringStatusList: {
|
|
1201
|
+
statusPurpose: bitstringEntity.statusPurpose,
|
|
1202
|
+
bitsPerStatus: bitstringEntity.bitsPerStatus,
|
|
1203
|
+
...bitstringEntity.validFrom && {
|
|
1204
|
+
validFrom: bitstringEntity.validFrom
|
|
1205
|
+
},
|
|
1206
|
+
...bitstringEntity.validUntil && {
|
|
1207
|
+
validUntil: bitstringEntity.validUntil
|
|
1208
|
+
},
|
|
1209
|
+
...bitstringEntity.ttl && {
|
|
1210
|
+
ttl: bitstringEntity.ttl
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
/**
|
|
1217
|
+
* Creates a credential status entry for a specific credential in a status list
|
|
1218
|
+
*
|
|
1219
|
+
* @param args - Parameters including the status list, entry details, and index
|
|
1220
|
+
* @returns Promise resolving to the credential status entry
|
|
1221
|
+
*/
|
|
1222
|
+
async createCredentialStatus(args) {
|
|
1223
|
+
const { statusList, statusListEntry, statusListIndex } = args;
|
|
1224
|
+
const bitstringStatusList = statusList;
|
|
1225
|
+
const bitstringStatusListEntry = statusListEntry;
|
|
1226
|
+
return {
|
|
1227
|
+
id: `${statusList.id}#${statusListIndex}`,
|
|
1228
|
+
type: "BitstringStatusListEntry",
|
|
1229
|
+
statusPurpose: bitstringStatusListEntry.statusPurpose,
|
|
1230
|
+
statusListIndex: "" + statusListIndex,
|
|
1231
|
+
statusListCredential: statusList.id,
|
|
1232
|
+
bitsPerStatus: bitstringStatusList.bitsPerStatus,
|
|
1233
|
+
statusMessage: bitstringStatusListEntry.statusMessage,
|
|
1234
|
+
statusReference: bitstringStatusListEntry.statusReference
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* Creates a signed verifiable credential from an unsigned status list credential
|
|
1239
|
+
*
|
|
1240
|
+
* @param args - Parameters including the unsigned credential and signing details
|
|
1241
|
+
* @param context - Veramo agent context for credential operations
|
|
1242
|
+
* @returns Promise resolving to the signed credential
|
|
1243
|
+
*/
|
|
1244
|
+
async createVerifiableCredential(args, context) {
|
|
1245
|
+
const { unsignedCredential, issuer, proofFormat, keyRef } = args;
|
|
1246
|
+
const identifier = await context.agent.identifierManagedGet({
|
|
1247
|
+
identifier: typeof issuer === "string" ? issuer : issuer.id,
|
|
1248
|
+
vmRelationship: "assertionMethod",
|
|
1249
|
+
offlineWhenNoDIDRegistered: true
|
|
1250
|
+
});
|
|
1251
|
+
const verifiableCredential = await context.agent.createVerifiableCredential({
|
|
1252
|
+
credential: unsignedCredential,
|
|
1253
|
+
keyRef: keyRef ?? identifier.kmsKeyRef,
|
|
1254
|
+
proofFormat,
|
|
1255
|
+
fetchRemoteContexts: true
|
|
1256
|
+
});
|
|
1257
|
+
return CredentialMapper3.toWrappedVerifiableCredential(verifiableCredential).original;
|
|
1258
|
+
}
|
|
1259
|
+
/**
|
|
1260
|
+
* Builds the appropriate content type string for a given proof format
|
|
1261
|
+
*
|
|
1262
|
+
* @param proofFormat - The proof format to build content type for
|
|
1263
|
+
* @returns The corresponding content type string
|
|
1264
|
+
*/
|
|
1265
|
+
buildContentType(proofFormat) {
|
|
1266
|
+
switch (proofFormat) {
|
|
1267
|
+
case "jwt":
|
|
1268
|
+
return "application/statuslist+jwt";
|
|
1269
|
+
case "cbor":
|
|
1270
|
+
return "application/statuslist+cwt";
|
|
1271
|
+
case "vc+jwt":
|
|
1272
|
+
return "application/statuslist+vc+jwt";
|
|
1273
|
+
case "lds":
|
|
1274
|
+
return "application/statuslist+ld+json";
|
|
1275
|
+
default:
|
|
1276
|
+
throw Error(`Unsupported content type '${proofFormat}' for status lists`);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
};
|
|
1280
|
+
|
|
1281
|
+
// src/impl/StatusListFactory.ts
|
|
713
1282
|
var StatusListFactory = class _StatusListFactory {
|
|
714
1283
|
static {
|
|
715
1284
|
__name(this, "StatusListFactory");
|
|
@@ -718,8 +1287,9 @@ var StatusListFactory = class _StatusListFactory {
|
|
|
718
1287
|
implementations;
|
|
719
1288
|
constructor() {
|
|
720
1289
|
this.implementations = /* @__PURE__ */ new Map();
|
|
721
|
-
this.implementations.set(
|
|
722
|
-
this.implementations.set(
|
|
1290
|
+
this.implementations.set(StatusListType5.StatusList2021, new StatusList2021Implementation());
|
|
1291
|
+
this.implementations.set(StatusListType5.OAuthStatusList, new OAuthStatusListImplementation());
|
|
1292
|
+
this.implementations.set(StatusListType5.BitstringStatusList, new BitstringStatusListImplementation());
|
|
723
1293
|
}
|
|
724
1294
|
static getInstance() {
|
|
725
1295
|
if (!_StatusListFactory.instance) {
|
|
@@ -792,7 +1362,7 @@ __name(vcLibCheckStatusFunction, "vcLibCheckStatusFunction");
|
|
|
792
1362
|
async function checkStatusForCredential(args) {
|
|
793
1363
|
const verifyStatusListCredential = args.verifyStatusListCredential ?? true;
|
|
794
1364
|
const verifyMatchingIssuers = args.verifyMatchingIssuers ?? true;
|
|
795
|
-
const uniform =
|
|
1365
|
+
const uniform = CredentialMapper4.toUniformCredential(args.credential);
|
|
796
1366
|
if (!("credentialStatus" in uniform) || !uniform.credentialStatus) {
|
|
797
1367
|
if (args.mandatoryCredentialStatus) {
|
|
798
1368
|
const error = "No credential status object found in the Verifiable Credential and it is mandatory";
|
|
@@ -807,7 +1377,7 @@ async function checkStatusForCredential(args) {
|
|
|
807
1377
|
};
|
|
808
1378
|
}
|
|
809
1379
|
if ("credentialStatus" in uniform && uniform.credentialStatus) {
|
|
810
|
-
if (uniform.credentialStatus.type === "StatusList2021Entry") {
|
|
1380
|
+
if (uniform.credentialStatus.type === "StatusList2021Entry" || uniform.credentialStatus.type === "BitstringStatusListEntry") {
|
|
811
1381
|
return checkStatus({
|
|
812
1382
|
...args,
|
|
813
1383
|
verifyStatusListCredential,
|
|
@@ -855,35 +1425,35 @@ async function updateStatusIndexFromStatusListCredential(args, context) {
|
|
|
855
1425
|
return implementation.updateStatusListIndex(args, context);
|
|
856
1426
|
}
|
|
857
1427
|
__name(updateStatusIndexFromStatusListCredential, "updateStatusIndexFromStatusListCredential");
|
|
858
|
-
async function
|
|
859
|
-
const
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
const type = uniform.type.find((t) => t.includes("StatusList2021") || t.includes("OAuth2StatusList"));
|
|
874
|
-
if (!type) {
|
|
875
|
-
throw new Error("Invalid status list credential type");
|
|
876
|
-
}
|
|
877
|
-
statusListType = type.replace("Credential", "");
|
|
1428
|
+
async function extractCredentialDetails(statusListCredential) {
|
|
1429
|
+
const statusListType = determineStatusListType(statusListCredential);
|
|
1430
|
+
const implementation = getStatusListImplementation(statusListType);
|
|
1431
|
+
return implementation.extractCredentialDetails(statusListCredential);
|
|
1432
|
+
}
|
|
1433
|
+
__name(extractCredentialDetails, "extractCredentialDetails");
|
|
1434
|
+
async function toStatusListDetails(args) {
|
|
1435
|
+
if ("statusListCredential" in args) {
|
|
1436
|
+
const statusListType = args.statusListType;
|
|
1437
|
+
const implementation = getStatusListImplementation(statusListType);
|
|
1438
|
+
return implementation.toStatusListDetails(args);
|
|
1439
|
+
} else {
|
|
1440
|
+
const statusListType = args.statusListEntity.type;
|
|
1441
|
+
const implementation = getStatusListImplementation(statusListType);
|
|
1442
|
+
return implementation.toStatusListDetails(args);
|
|
878
1443
|
}
|
|
1444
|
+
}
|
|
1445
|
+
__name(toStatusListDetails, "toStatusListDetails");
|
|
1446
|
+
async function createCredentialStatusFromStatusList(args) {
|
|
1447
|
+
const { statusList, statusListEntry, statusListIndex } = args;
|
|
1448
|
+
const statusListType = determineStatusListType(statusList.statusListCredential);
|
|
879
1449
|
const implementation = getStatusListImplementation(statusListType);
|
|
880
|
-
return
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
1450
|
+
return implementation.createCredentialStatus({
|
|
1451
|
+
statusList,
|
|
1452
|
+
statusListEntry,
|
|
1453
|
+
statusListIndex
|
|
884
1454
|
});
|
|
885
1455
|
}
|
|
886
|
-
__name(
|
|
1456
|
+
__name(createCredentialStatusFromStatusList, "createCredentialStatusFromStatusList");
|
|
887
1457
|
async function updateStatusListIndexFromEncodedList(args, context) {
|
|
888
1458
|
const { type } = getAssertedValue("type", args);
|
|
889
1459
|
const implementation = getStatusListImplementation(type);
|
|
@@ -898,7 +1468,7 @@ async function statusList2021ToVerifiableCredential(args, context) {
|
|
|
898
1468
|
offlineWhenNoDIDRegistered: true
|
|
899
1469
|
});
|
|
900
1470
|
const proofFormat = args?.proofFormat ?? "lds";
|
|
901
|
-
assertValidProofType(
|
|
1471
|
+
assertValidProofType(StatusListType6.StatusList2021, proofFormat);
|
|
902
1472
|
const veramoProofFormat = proofFormat;
|
|
903
1473
|
const encodedList = getAssertedValue("encodedList", args.encodedList);
|
|
904
1474
|
const statusPurpose = getAssertedValue("statusPurpose", args.statusPurpose);
|
|
@@ -927,7 +1497,7 @@ async function statusList2021ToVerifiableCredential(args, context) {
|
|
|
927
1497
|
proofFormat: veramoProofFormat,
|
|
928
1498
|
fetchRemoteContexts: true
|
|
929
1499
|
});
|
|
930
|
-
return
|
|
1500
|
+
return CredentialMapper4.toWrappedVerifiableCredential(verifiableCredential).original;
|
|
931
1501
|
}
|
|
932
1502
|
__name(statusList2021ToVerifiableCredential, "statusList2021ToVerifiableCredential");
|
|
933
1503
|
export {
|
|
@@ -935,12 +1505,15 @@ export {
|
|
|
935
1505
|
StatusOAuth,
|
|
936
1506
|
checkStatusForCredential,
|
|
937
1507
|
checkStatusIndexFromStatusListCredential,
|
|
1508
|
+
createCredentialStatusFromStatusList,
|
|
938
1509
|
createNewStatusList,
|
|
1510
|
+
determineStatusListType,
|
|
1511
|
+
extractCredentialDetails,
|
|
939
1512
|
fetchStatusListCredential,
|
|
940
1513
|
simpleCheckStatusFromStatusListUrl,
|
|
941
1514
|
statusList2021ToVerifiableCredential,
|
|
942
|
-
statusListCredentialToDetails,
|
|
943
1515
|
statusPluginStatusFunction,
|
|
1516
|
+
toStatusListDetails,
|
|
944
1517
|
updateStatusIndexFromStatusListCredential,
|
|
945
1518
|
updateStatusListIndexFromEncodedList,
|
|
946
1519
|
vcLibCheckStatusFunction
|