@sphereon/ssi-sdk.vc-status-list 0.34.1-feature.SSISDK.17.bitstring.sl.2 → 0.34.1-feature.SSISDK.17.bitstring.sl.24
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 +545 -242
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +158 -78
- package/dist/index.d.ts +158 -78
- package/dist/index.js +546 -243
- package/dist/index.js.map +1 -1
- package/package.json +10 -9
- package/src/functions.ts +126 -48
- package/src/impl/BitstringStatusListImplementation.ts +319 -157
- package/src/impl/IStatusList.ts +102 -9
- package/src/impl/OAuthStatusList.ts +126 -35
- package/src/impl/StatusList2021.ts +112 -32
- package/src/index.ts +1 -0
- package/src/types/BitstringStatusList.ts +3 -41
- package/src/types/index.ts +48 -80
- package/src/utils.ts +81 -19
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ var Status2021 = /* @__PURE__ */ function(Status20212) {
|
|
|
15
15
|
}({});
|
|
16
16
|
|
|
17
17
|
// src/functions.ts
|
|
18
|
-
import { CredentialMapper as CredentialMapper4,
|
|
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
|
}
|
|
@@ -71,6 +72,13 @@ var ValidProofTypeMap = /* @__PURE__ */ new Map([
|
|
|
71
72
|
"jwt",
|
|
72
73
|
"cbor"
|
|
73
74
|
]
|
|
75
|
+
],
|
|
76
|
+
[
|
|
77
|
+
StatusListType.BitstringStatusList,
|
|
78
|
+
[
|
|
79
|
+
"lds",
|
|
80
|
+
"vc+jwt"
|
|
81
|
+
]
|
|
74
82
|
]
|
|
75
83
|
]);
|
|
76
84
|
function assertValidProofType(type, proofFormat) {
|
|
@@ -84,29 +92,50 @@ function determineStatusListType(credential) {
|
|
|
84
92
|
const proofFormat = determineProofFormat(credential);
|
|
85
93
|
switch (proofFormat) {
|
|
86
94
|
case "jwt":
|
|
87
|
-
|
|
88
|
-
const keys = Object.keys(payload);
|
|
89
|
-
if (keys.includes("status_list")) {
|
|
90
|
-
return StatusListType.OAuthStatusList;
|
|
91
|
-
} else if (keys.includes("vc")) {
|
|
92
|
-
return StatusListType.StatusList2021;
|
|
93
|
-
}
|
|
94
|
-
break;
|
|
95
|
+
return determineJwtStatusListType(credential);
|
|
95
96
|
case "lds":
|
|
96
|
-
|
|
97
|
-
const type = uniform.type.find((t) => {
|
|
98
|
-
return Object.values(StatusListType).some((statusType) => t.includes(statusType));
|
|
99
|
-
});
|
|
100
|
-
if (!type) {
|
|
101
|
-
throw new Error("Invalid status list credential type");
|
|
102
|
-
}
|
|
103
|
-
return type.replace("Credential", "");
|
|
97
|
+
return determineLdsStatusListType(credential);
|
|
104
98
|
case "cbor":
|
|
105
99
|
return StatusListType.OAuthStatusList;
|
|
100
|
+
default:
|
|
101
|
+
throw new Error("Cannot determine status list type from credential payload");
|
|
106
102
|
}
|
|
107
|
-
throw new Error("Cannot determine status list type from credential payload");
|
|
108
103
|
}
|
|
109
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");
|
|
110
139
|
function determineProofFormat(credential) {
|
|
111
140
|
const type = CredentialMapper.detectDocumentType(credential);
|
|
112
141
|
switch (type) {
|
|
@@ -121,6 +150,26 @@ function determineProofFormat(credential) {
|
|
|
121
150
|
}
|
|
122
151
|
}
|
|
123
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");
|
|
124
173
|
|
|
125
174
|
// src/impl/StatusList2021.ts
|
|
126
175
|
import { CredentialMapper as CredentialMapper2, DocumentFormat as DocumentFormat2, StatusListType as StatusListType2 } from "@sphereon/ssi-types";
|
|
@@ -184,13 +233,14 @@ var StatusList2021Implementation = class {
|
|
|
184
233
|
encodedList,
|
|
185
234
|
proofFormat
|
|
186
235
|
}, context);
|
|
236
|
+
if (!("statusPurpose" in credentialSubject)) {
|
|
237
|
+
return Promise.reject(Error("statusPurpose is required in credentialSubject for StatusList2021"));
|
|
238
|
+
}
|
|
187
239
|
return {
|
|
188
240
|
statusListCredential: updatedCredential,
|
|
189
241
|
encodedList,
|
|
190
242
|
statusList2021: {
|
|
191
|
-
|
|
192
|
-
statusPurpose: credentialSubject.statusPurpose
|
|
193
|
-
} : {},
|
|
243
|
+
statusPurpose: credentialSubject.statusPurpose,
|
|
194
244
|
indexingDirection: "rightToLeft"
|
|
195
245
|
},
|
|
196
246
|
length: statusList.length - 1,
|
|
@@ -213,7 +263,7 @@ var StatusList2021Implementation = class {
|
|
|
213
263
|
encodedList: args.encodedList
|
|
214
264
|
});
|
|
215
265
|
const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
|
|
216
|
-
statusList.setStatus(index, args.value);
|
|
266
|
+
statusList.setStatus(index, args.value !== 0);
|
|
217
267
|
const newEncodedList = await statusList.encode();
|
|
218
268
|
const credential = await this.createVerifiableCredential({
|
|
219
269
|
id,
|
|
@@ -247,36 +297,88 @@ var StatusList2021Implementation = class {
|
|
|
247
297
|
const status = statusList.getStatus(typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex));
|
|
248
298
|
return status ? Status2021.Invalid : Status2021.Valid;
|
|
249
299
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
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);
|
|
253
307
|
const { issuer, credentialSubject } = uniform;
|
|
254
|
-
const
|
|
255
|
-
const encodedList = getAssertedProperty("encodedList", credentialSubject);
|
|
256
|
-
const proofFormat = CredentialMapper2.detectDocumentType(statusListPayload) === DocumentFormat2.JWT ? "jwt" : "lds";
|
|
257
|
-
const statusPurpose = getAssertedProperty("statusPurpose", credentialSubject);
|
|
258
|
-
const list = await StatusList.decode({
|
|
259
|
-
encodedList
|
|
260
|
-
});
|
|
308
|
+
const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
261
309
|
return {
|
|
262
|
-
id,
|
|
263
|
-
encodedList,
|
|
310
|
+
id: getAssertedValue("id", uniform.id),
|
|
264
311
|
issuer,
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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,
|
|
271
339
|
indexingDirection: "rightToLeft",
|
|
272
|
-
statusPurpose
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
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
|
|
280
382
|
};
|
|
281
383
|
}
|
|
282
384
|
async createVerifiableCredential(args, context) {
|
|
@@ -571,7 +673,8 @@ var OAuthStatusListImplementation = class {
|
|
|
571
673
|
}
|
|
572
674
|
const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT2;
|
|
573
675
|
const { issuer, id, oauthStatusList, keyRef } = args;
|
|
574
|
-
const { bitsPerStatus
|
|
676
|
+
const { bitsPerStatus } = oauthStatusList;
|
|
677
|
+
const expiresAt = ensureDate(oauthStatusList.expiresAt);
|
|
575
678
|
const length = args.length ?? DEFAULT_LIST_LENGTH2;
|
|
576
679
|
const issuerString = typeof issuer === "string" ? issuer : issuer.id;
|
|
577
680
|
const correlationId = getAssertedValue("correlationId", args.correlationId);
|
|
@@ -594,7 +697,8 @@ var OAuthStatusListImplementation = class {
|
|
|
594
697
|
};
|
|
595
698
|
}
|
|
596
699
|
async updateStatusListIndex(args, context) {
|
|
597
|
-
const { statusListCredential, value,
|
|
700
|
+
const { statusListCredential, value, keyRef } = args;
|
|
701
|
+
const expiresAt = ensureDate(args.expiresAt);
|
|
598
702
|
if (typeof statusListCredential !== "string") {
|
|
599
703
|
return Promise.reject("statusListCredential in neither JWT nor CWT");
|
|
600
704
|
}
|
|
@@ -630,12 +734,13 @@ var OAuthStatusListImplementation = class {
|
|
|
630
734
|
throw new Error("OAuthStatusList options are required for type OAuthStatusList");
|
|
631
735
|
}
|
|
632
736
|
const { proofFormat, oauthStatusList, keyRef } = args;
|
|
633
|
-
const { bitsPerStatus
|
|
737
|
+
const { bitsPerStatus } = oauthStatusList;
|
|
738
|
+
const expiresAt = ensureDate(oauthStatusList.expiresAt);
|
|
634
739
|
const { issuer, id } = getAssertedValues(args);
|
|
635
740
|
const issuerString = typeof issuer === "string" ? issuer : issuer.id;
|
|
636
741
|
const listToUpdate = StatusList4.decompressStatusList(args.encodedList, bitsPerStatus ?? DEFAULT_BITS_PER_STATUS);
|
|
637
742
|
const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
|
|
638
|
-
listToUpdate.setStatus(index, args.value
|
|
743
|
+
listToUpdate.setStatus(index, args.value);
|
|
639
744
|
const { statusListCredential, encodedList } = await this.createSignedStatusList(proofFormat ?? DEFAULT_PROOF_FORMAT2, context, listToUpdate, issuerString, id, expiresAt, keyRef);
|
|
640
745
|
return {
|
|
641
746
|
encodedList,
|
|
@@ -652,9 +757,6 @@ var OAuthStatusListImplementation = class {
|
|
|
652
757
|
statuslistContentType: this.buildContentType(proofFormat)
|
|
653
758
|
};
|
|
654
759
|
}
|
|
655
|
-
buildContentType(proofFormat) {
|
|
656
|
-
return `application/statuslist+${proofFormat === "cbor" ? "cwt" : "jwt"}`;
|
|
657
|
-
}
|
|
658
760
|
async checkStatusIndex(args) {
|
|
659
761
|
const { statusListCredential, statusListIndex } = args;
|
|
660
762
|
if (typeof statusListCredential !== "string") {
|
|
@@ -668,34 +770,101 @@ var OAuthStatusListImplementation = class {
|
|
|
668
770
|
}
|
|
669
771
|
return statusList.getStatus(index);
|
|
670
772
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
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);
|
|
676
784
|
return {
|
|
677
|
-
id,
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
expiresAt: new Date(exp * 1e3)
|
|
689
|
-
}
|
|
690
|
-
},
|
|
691
|
-
...args.correlationId && {
|
|
692
|
-
correlationId: args.correlationId
|
|
693
|
-
},
|
|
694
|
-
...args.driverType && {
|
|
695
|
-
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"));
|
|
696
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
|
|
697
863
|
};
|
|
698
864
|
}
|
|
865
|
+
buildContentType(proofFormat) {
|
|
866
|
+
return `application/statuslist+${proofFormat === "cbor" ? "cwt" : "jwt"}`;
|
|
867
|
+
}
|
|
699
868
|
async createSignedStatusList(proofFormat, context, statusList, issuerString, id, expiresAt, keyRef) {
|
|
700
869
|
switch (proofFormat) {
|
|
701
870
|
case "jwt": {
|
|
@@ -715,15 +884,21 @@ import { StatusListType as StatusListType5 } from "@sphereon/ssi-types";
|
|
|
715
884
|
|
|
716
885
|
// src/impl/BitstringStatusListImplementation.ts
|
|
717
886
|
import { CredentialMapper as CredentialMapper3, DocumentFormat as DocumentFormat3, StatusListType as StatusListType4 } from "@sphereon/ssi-types";
|
|
718
|
-
import {
|
|
887
|
+
import { BitstreamStatusList, createStatusListCredential } from "@4sure-tech/vc-bitstring-status-lists";
|
|
719
888
|
var DEFAULT_LIST_LENGTH3 = 131072;
|
|
720
|
-
var DEFAULT_PROOF_FORMAT3 = "
|
|
721
|
-
var DEFAULT_STATUS_SIZE = 1;
|
|
889
|
+
var DEFAULT_PROOF_FORMAT3 = "vc+jwt";
|
|
722
890
|
var DEFAULT_STATUS_PURPOSE = "revocation";
|
|
723
891
|
var BitstringStatusListImplementation = class {
|
|
724
892
|
static {
|
|
725
893
|
__name(this, "BitstringStatusListImplementation");
|
|
726
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
|
+
*/
|
|
727
902
|
async createNewStatusList(args, context) {
|
|
728
903
|
if (!args.bitstringStatusList) {
|
|
729
904
|
throw new Error("BitstringStatusList options are required for type BitstringStatusList");
|
|
@@ -731,29 +906,37 @@ var BitstringStatusListImplementation = class {
|
|
|
731
906
|
const length = args?.length ?? DEFAULT_LIST_LENGTH3;
|
|
732
907
|
const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT3;
|
|
733
908
|
assertValidProofType(StatusListType4.BitstringStatusList, proofFormat);
|
|
734
|
-
const veramoProofFormat = proofFormat;
|
|
735
909
|
const { issuer, id } = args;
|
|
736
910
|
const correlationId = getAssertedValue("correlationId", args.correlationId);
|
|
737
|
-
const { statusPurpose,
|
|
738
|
-
const
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
const encodedList = await list.encode();
|
|
742
|
-
const statusListCredential = await this.createVerifiableCredential({
|
|
743
|
-
...args,
|
|
744
|
-
encodedList,
|
|
745
|
-
proofFormat: veramoProofFormat,
|
|
911
|
+
const { statusPurpose, bitsPerStatus, validFrom, validUntil, ttl } = args.bitstringStatusList;
|
|
912
|
+
const unsignedCredential = await createStatusListCredential({
|
|
913
|
+
id,
|
|
914
|
+
issuer,
|
|
746
915
|
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
747
|
-
|
|
748
|
-
|
|
916
|
+
validFrom: ensureDate(validFrom),
|
|
917
|
+
validUntil: ensureDate(validUntil),
|
|
749
918
|
ttl
|
|
919
|
+
});
|
|
920
|
+
const statusListCredential = await this.createVerifiableCredential({
|
|
921
|
+
unsignedCredential,
|
|
922
|
+
id,
|
|
923
|
+
issuer,
|
|
924
|
+
proofFormat,
|
|
925
|
+
keyRef: args.keyRef
|
|
750
926
|
}, context);
|
|
751
927
|
return {
|
|
752
|
-
encodedList,
|
|
928
|
+
encodedList: unsignedCredential.credentialSubject.encodedList,
|
|
753
929
|
statusListCredential,
|
|
754
930
|
bitstringStatusList: {
|
|
755
931
|
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
756
|
-
|
|
932
|
+
...unsignedCredential.validFrom && {
|
|
933
|
+
validFrom: new Date(unsignedCredential.validFrom)
|
|
934
|
+
},
|
|
935
|
+
...unsignedCredential.validUntil && {
|
|
936
|
+
validUntil: new Date(unsignedCredential.validUntil)
|
|
937
|
+
},
|
|
938
|
+
ttl,
|
|
939
|
+
bitsPerStatus
|
|
757
940
|
},
|
|
758
941
|
length,
|
|
759
942
|
type: StatusListType4.BitstringStatusList,
|
|
@@ -764,45 +947,66 @@ var BitstringStatusListImplementation = class {
|
|
|
764
947
|
statuslistContentType: this.buildContentType(proofFormat)
|
|
765
948
|
};
|
|
766
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
|
+
*/
|
|
767
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
|
+
}
|
|
768
961
|
const credential = args.statusListCredential;
|
|
769
962
|
const uniform = CredentialMapper3.toUniformCredential(credential);
|
|
770
963
|
const { issuer, credentialSubject } = uniform;
|
|
771
964
|
const id = getAssertedValue("id", uniform.id);
|
|
772
965
|
const origEncodedList = getAssertedProperty("encodedList", credentialSubject);
|
|
773
966
|
const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
|
|
774
|
-
const statusList = await
|
|
775
|
-
encodedList: origEncodedList
|
|
967
|
+
const statusList = await BitstreamStatusList.decode({
|
|
968
|
+
encodedList: origEncodedList,
|
|
969
|
+
statusSize: args.bitsPerStatus
|
|
776
970
|
});
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
const proofFormat = CredentialMapper3.detectDocumentType(credential) === DocumentFormat3.JWT ? "jwt" : "lds";
|
|
971
|
+
const bitstringStatusId = args.value;
|
|
972
|
+
statusList.setStatus(index, bitstringStatusId);
|
|
973
|
+
const proofFormat = CredentialMapper3.detectDocumentType(credential) === DocumentFormat3.JWT ? "vc+jwt" : "lds";
|
|
780
974
|
const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
781
975
|
const statusPurpose = getAssertedProperty("statusPurpose", credSubject);
|
|
782
976
|
const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : void 0;
|
|
783
977
|
const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : void 0;
|
|
784
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
|
+
});
|
|
785
988
|
const updatedCredential = await this.createVerifiableCredential({
|
|
786
|
-
|
|
989
|
+
unsignedCredential,
|
|
787
990
|
id,
|
|
788
991
|
issuer,
|
|
789
|
-
encodedList,
|
|
790
992
|
proofFormat,
|
|
791
|
-
|
|
792
|
-
ttl,
|
|
793
|
-
validFrom,
|
|
794
|
-
validUntil
|
|
993
|
+
keyRef: args.keyRef
|
|
795
994
|
}, context);
|
|
796
995
|
return {
|
|
797
996
|
statusListCredential: updatedCredential,
|
|
798
|
-
encodedList,
|
|
997
|
+
encodedList: unsignedCredential.credentialSubject.encodedList,
|
|
799
998
|
bitstringStatusList: {
|
|
800
999
|
statusPurpose,
|
|
801
|
-
validFrom
|
|
802
|
-
|
|
1000
|
+
...unsignedCredential.validFrom && {
|
|
1001
|
+
validFrom: new Date(unsignedCredential.validFrom)
|
|
1002
|
+
},
|
|
1003
|
+
...unsignedCredential.validUntil && {
|
|
1004
|
+
validUntil: new Date(unsignedCredential.validUntil)
|
|
1005
|
+
},
|
|
1006
|
+
bitsPerStatus: args.bitsPerStatus,
|
|
803
1007
|
ttl
|
|
804
1008
|
},
|
|
805
|
-
length: statusList.
|
|
1009
|
+
length: statusList.getLength(),
|
|
806
1010
|
type: StatusListType4.BitstringStatusList,
|
|
807
1011
|
proofFormat,
|
|
808
1012
|
id,
|
|
@@ -810,166 +1014,262 @@ var BitstringStatusListImplementation = class {
|
|
|
810
1014
|
statuslistContentType: this.buildContentType(proofFormat)
|
|
811
1015
|
};
|
|
812
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
|
+
*/
|
|
813
1024
|
async updateStatusListFromEncodedList(args, context) {
|
|
814
1025
|
if (!args.bitstringStatusList) {
|
|
815
1026
|
throw new Error("bitstringStatusList options required for type BitstringStatusList");
|
|
816
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;
|
|
817
1032
|
const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT3;
|
|
818
1033
|
assertValidProofType(StatusListType4.BitstringStatusList, proofFormat);
|
|
819
|
-
const veramoProofFormat = proofFormat;
|
|
820
1034
|
const { issuer, id } = getAssertedValues(args);
|
|
821
|
-
const statusList = await
|
|
822
|
-
encodedList: args.encodedList
|
|
1035
|
+
const statusList = await BitstreamStatusList.decode({
|
|
1036
|
+
encodedList: args.encodedList,
|
|
1037
|
+
statusSize: bitsPerStatus
|
|
823
1038
|
});
|
|
824
1039
|
const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
|
|
825
1040
|
statusList.setStatus(index, args.value);
|
|
826
|
-
const
|
|
827
|
-
const { statusPurpose, statusSize, statusMessage, ttl, validFrom, validUntil } = args.bitstringStatusList;
|
|
828
|
-
const credential = await this.createVerifiableCredential({
|
|
1041
|
+
const unsignedCredential = await createStatusListCredential({
|
|
829
1042
|
id,
|
|
830
1043
|
issuer,
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
statusSize,
|
|
836
|
-
statusMessage,
|
|
837
|
-
validFrom,
|
|
838
|
-
validUntil,
|
|
1044
|
+
statusList,
|
|
1045
|
+
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
1046
|
+
validFrom: ensureDate(validFrom),
|
|
1047
|
+
validUntil: ensureDate(validUntil),
|
|
839
1048
|
ttl
|
|
1049
|
+
});
|
|
1050
|
+
const credential = await this.createVerifiableCredential({
|
|
1051
|
+
unsignedCredential,
|
|
1052
|
+
id,
|
|
1053
|
+
issuer,
|
|
1054
|
+
proofFormat,
|
|
1055
|
+
keyRef: args.keyRef
|
|
840
1056
|
}, context);
|
|
841
1057
|
return {
|
|
842
1058
|
type: StatusListType4.BitstringStatusList,
|
|
843
1059
|
statusListCredential: credential,
|
|
844
|
-
encodedList:
|
|
1060
|
+
encodedList: unsignedCredential.credentialSubject.encodedList,
|
|
845
1061
|
bitstringStatusList: {
|
|
846
1062
|
statusPurpose,
|
|
847
|
-
|
|
848
|
-
|
|
1063
|
+
bitsPerStatus,
|
|
1064
|
+
...unsignedCredential.validFrom && {
|
|
1065
|
+
validFrom: new Date(unsignedCredential.validFrom)
|
|
1066
|
+
},
|
|
1067
|
+
...unsignedCredential.validUntil && {
|
|
1068
|
+
validUntil: new Date(unsignedCredential.validUntil)
|
|
1069
|
+
},
|
|
849
1070
|
ttl
|
|
850
1071
|
},
|
|
851
|
-
length: statusList.
|
|
1072
|
+
length: statusList.getLength(),
|
|
852
1073
|
proofFormat: args.proofFormat ?? "lds",
|
|
853
1074
|
id,
|
|
854
1075
|
issuer,
|
|
855
1076
|
statuslistContentType: this.buildContentType(proofFormat)
|
|
856
1077
|
};
|
|
857
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
|
+
*/
|
|
858
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
|
+
}
|
|
859
1089
|
const uniform = CredentialMapper3.toUniformCredential(args.statusListCredential);
|
|
860
1090
|
const { credentialSubject } = uniform;
|
|
861
1091
|
const encodedList = getAssertedProperty("encodedList", credentialSubject);
|
|
862
|
-
const
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
const hexIndex = `0x${numIndex.toString(16)}`;
|
|
866
|
-
const statusMessage = messageList.find((statMsg) => statMsg.status === hexIndex);
|
|
867
|
-
const statusList = await decodeList({
|
|
868
|
-
encodedList
|
|
1092
|
+
const statusList = await BitstreamStatusList.decode({
|
|
1093
|
+
encodedList,
|
|
1094
|
+
statusSize: args.bitsPerStatus
|
|
869
1095
|
});
|
|
870
|
-
|
|
871
|
-
|
|
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}`);
|
|
872
1099
|
}
|
|
873
|
-
|
|
874
|
-
return {
|
|
875
|
-
index: numIndex,
|
|
876
|
-
status: hexIndex,
|
|
877
|
-
message: statusMessage?.message,
|
|
878
|
-
set: value
|
|
879
|
-
};
|
|
1100
|
+
return statusList.getStatus(numIndex);
|
|
880
1101
|
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
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);
|
|
884
1109
|
const { issuer, credentialSubject } = uniform;
|
|
885
|
-
const
|
|
886
|
-
const encodedList = getAssertedProperty("encodedList", credentialSubject);
|
|
887
|
-
const proofFormat = CredentialMapper3.detectDocumentType(statusListPayload) === DocumentFormat3.JWT ? "jwt" : "lds";
|
|
888
|
-
const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
889
|
-
const statusPurpose = getAssertedProperty("statusPurpose", credSubject);
|
|
890
|
-
const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : void 0;
|
|
891
|
-
const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : void 0;
|
|
892
|
-
const ttl = credSubject.ttl;
|
|
893
|
-
const list = await decodeList({
|
|
894
|
-
encodedList
|
|
895
|
-
});
|
|
1110
|
+
const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
896
1111
|
return {
|
|
897
|
-
id,
|
|
898
|
-
encodedList,
|
|
1112
|
+
id: getAssertedValue("id", uniform.id),
|
|
899
1113
|
issuer,
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
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,
|
|
906
1145
|
statusPurpose,
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
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"));
|
|
916
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
|
|
917
1235
|
};
|
|
918
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
|
+
*/
|
|
919
1244
|
async createVerifiableCredential(args, context) {
|
|
1245
|
+
const { unsignedCredential, issuer, proofFormat, keyRef } = args;
|
|
920
1246
|
const identifier = await context.agent.identifierManagedGet({
|
|
921
|
-
identifier: typeof
|
|
1247
|
+
identifier: typeof issuer === "string" ? issuer : issuer.id,
|
|
922
1248
|
vmRelationship: "assertionMethod",
|
|
923
1249
|
offlineWhenNoDIDRegistered: true
|
|
924
1250
|
});
|
|
925
|
-
const credentialSubject = {
|
|
926
|
-
id: args.id,
|
|
927
|
-
type: "BitstringStatusList",
|
|
928
|
-
statusPurpose: args.statusPurpose,
|
|
929
|
-
encodedList: args.encodedList
|
|
930
|
-
};
|
|
931
|
-
if (args.statusSize && args.statusSize > 1) {
|
|
932
|
-
credentialSubject.statusSize = args.statusSize;
|
|
933
|
-
}
|
|
934
|
-
if (args.statusMessage) {
|
|
935
|
-
credentialSubject.statusMessage = args.statusMessage;
|
|
936
|
-
}
|
|
937
|
-
if (args.validFrom) {
|
|
938
|
-
credentialSubject.validFrom = args.validFrom;
|
|
939
|
-
}
|
|
940
|
-
if (args.validUntil) {
|
|
941
|
-
credentialSubject.validUntil = args.validUntil;
|
|
942
|
-
}
|
|
943
|
-
if (args.ttl) {
|
|
944
|
-
credentialSubject.ttl = args.ttl;
|
|
945
|
-
}
|
|
946
|
-
const credential = {
|
|
947
|
-
"@context": [
|
|
948
|
-
"https://www.w3.org/2018/credentials/v1",
|
|
949
|
-
"https://www.w3.org/ns/credentials/status/v1"
|
|
950
|
-
],
|
|
951
|
-
id: args.id,
|
|
952
|
-
issuer: args.issuer,
|
|
953
|
-
type: [
|
|
954
|
-
"VerifiableCredential",
|
|
955
|
-
"BitstringStatusListCredential"
|
|
956
|
-
],
|
|
957
|
-
credentialSubject
|
|
958
|
-
};
|
|
959
1251
|
const verifiableCredential = await context.agent.createVerifiableCredential({
|
|
960
|
-
credential,
|
|
961
|
-
keyRef:
|
|
962
|
-
proofFormat
|
|
1252
|
+
credential: unsignedCredential,
|
|
1253
|
+
keyRef: keyRef ?? identifier.kmsKeyRef,
|
|
1254
|
+
proofFormat,
|
|
963
1255
|
fetchRemoteContexts: true
|
|
964
1256
|
});
|
|
965
1257
|
return CredentialMapper3.toWrappedVerifiableCredential(verifiableCredential).original;
|
|
966
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
|
+
*/
|
|
967
1265
|
buildContentType(proofFormat) {
|
|
968
1266
|
switch (proofFormat) {
|
|
969
1267
|
case "jwt":
|
|
970
|
-
return
|
|
1268
|
+
return "application/statuslist+jwt";
|
|
971
1269
|
case "cbor":
|
|
972
|
-
return
|
|
1270
|
+
return "application/statuslist+cwt";
|
|
1271
|
+
case "vc+jwt":
|
|
1272
|
+
return "application/statuslist+vc+jwt";
|
|
973
1273
|
case "lds":
|
|
974
1274
|
return "application/statuslist+ld+json";
|
|
975
1275
|
default:
|
|
@@ -1125,35 +1425,35 @@ async function updateStatusIndexFromStatusListCredential(args, context) {
|
|
|
1125
1425
|
return implementation.updateStatusListIndex(args, context);
|
|
1126
1426
|
}
|
|
1127
1427
|
__name(updateStatusIndexFromStatusListCredential, "updateStatusIndexFromStatusListCredential");
|
|
1128
|
-
async function
|
|
1129
|
-
const
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
const type = uniform.type.find((t) => t.includes("StatusList2021") || t.includes("OAuth2StatusList") || t.includes("BitstringStatusList"));
|
|
1144
|
-
if (!type) {
|
|
1145
|
-
throw new Error("Invalid status list credential type");
|
|
1146
|
-
}
|
|
1147
|
-
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);
|
|
1148
1443
|
}
|
|
1444
|
+
}
|
|
1445
|
+
__name(toStatusListDetails, "toStatusListDetails");
|
|
1446
|
+
async function createCredentialStatusFromStatusList(args) {
|
|
1447
|
+
const { statusList, statusListEntry, statusListIndex } = args;
|
|
1448
|
+
const statusListType = determineStatusListType(statusList.statusListCredential);
|
|
1149
1449
|
const implementation = getStatusListImplementation(statusListType);
|
|
1150
|
-
return
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1450
|
+
return implementation.createCredentialStatus({
|
|
1451
|
+
statusList,
|
|
1452
|
+
statusListEntry,
|
|
1453
|
+
statusListIndex
|
|
1154
1454
|
});
|
|
1155
1455
|
}
|
|
1156
|
-
__name(
|
|
1456
|
+
__name(createCredentialStatusFromStatusList, "createCredentialStatusFromStatusList");
|
|
1157
1457
|
async function updateStatusListIndexFromEncodedList(args, context) {
|
|
1158
1458
|
const { type } = getAssertedValue("type", args);
|
|
1159
1459
|
const implementation = getStatusListImplementation(type);
|
|
@@ -1205,12 +1505,15 @@ export {
|
|
|
1205
1505
|
StatusOAuth,
|
|
1206
1506
|
checkStatusForCredential,
|
|
1207
1507
|
checkStatusIndexFromStatusListCredential,
|
|
1508
|
+
createCredentialStatusFromStatusList,
|
|
1208
1509
|
createNewStatusList,
|
|
1510
|
+
determineStatusListType,
|
|
1511
|
+
extractCredentialDetails,
|
|
1209
1512
|
fetchStatusListCredential,
|
|
1210
1513
|
simpleCheckStatusFromStatusListUrl,
|
|
1211
1514
|
statusList2021ToVerifiableCredential,
|
|
1212
|
-
statusListCredentialToDetails,
|
|
1213
1515
|
statusPluginStatusFunction,
|
|
1516
|
+
toStatusListDetails,
|
|
1214
1517
|
updateStatusIndexFromStatusListCredential,
|
|
1215
1518
|
updateStatusListIndexFromEncodedList,
|
|
1216
1519
|
vcLibCheckStatusFunction
|