@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.cjs
CHANGED
|
@@ -35,12 +35,15 @@ __export(index_exports, {
|
|
|
35
35
|
StatusOAuth: () => StatusOAuth,
|
|
36
36
|
checkStatusForCredential: () => checkStatusForCredential,
|
|
37
37
|
checkStatusIndexFromStatusListCredential: () => checkStatusIndexFromStatusListCredential,
|
|
38
|
+
createCredentialStatusFromStatusList: () => createCredentialStatusFromStatusList,
|
|
38
39
|
createNewStatusList: () => createNewStatusList,
|
|
40
|
+
determineStatusListType: () => determineStatusListType,
|
|
41
|
+
extractCredentialDetails: () => extractCredentialDetails,
|
|
39
42
|
fetchStatusListCredential: () => fetchStatusListCredential,
|
|
40
43
|
simpleCheckStatusFromStatusListUrl: () => simpleCheckStatusFromStatusListUrl,
|
|
41
44
|
statusList2021ToVerifiableCredential: () => statusList2021ToVerifiableCredential,
|
|
42
|
-
statusListCredentialToDetails: () => statusListCredentialToDetails,
|
|
43
45
|
statusPluginStatusFunction: () => statusPluginStatusFunction,
|
|
46
|
+
toStatusListDetails: () => toStatusListDetails,
|
|
44
47
|
updateStatusIndexFromStatusListCredential: () => updateStatusIndexFromStatusListCredential,
|
|
45
48
|
updateStatusListIndexFromEncodedList: () => updateStatusListIndexFromEncodedList,
|
|
46
49
|
vcLibCheckStatusFunction: () => vcLibCheckStatusFunction
|
|
@@ -71,7 +74,8 @@ function getAssertedStatusListType(type) {
|
|
|
71
74
|
const assertedType = type ?? import_ssi_types.StatusListType.StatusList2021;
|
|
72
75
|
if (![
|
|
73
76
|
import_ssi_types.StatusListType.StatusList2021,
|
|
74
|
-
import_ssi_types.StatusListType.OAuthStatusList
|
|
77
|
+
import_ssi_types.StatusListType.OAuthStatusList,
|
|
78
|
+
import_ssi_types.StatusListType.BitstringStatusList
|
|
75
79
|
].includes(assertedType)) {
|
|
76
80
|
throw Error(`StatusList type ${assertedType} is not supported (yet)`);
|
|
77
81
|
}
|
|
@@ -117,6 +121,13 @@ var ValidProofTypeMap = /* @__PURE__ */ new Map([
|
|
|
117
121
|
"jwt",
|
|
118
122
|
"cbor"
|
|
119
123
|
]
|
|
124
|
+
],
|
|
125
|
+
[
|
|
126
|
+
import_ssi_types.StatusListType.BitstringStatusList,
|
|
127
|
+
[
|
|
128
|
+
"lds",
|
|
129
|
+
"vc+jwt"
|
|
130
|
+
]
|
|
120
131
|
]
|
|
121
132
|
]);
|
|
122
133
|
function assertValidProofType(type, proofFormat) {
|
|
@@ -130,29 +141,50 @@ function determineStatusListType(credential) {
|
|
|
130
141
|
const proofFormat = determineProofFormat(credential);
|
|
131
142
|
switch (proofFormat) {
|
|
132
143
|
case "jwt":
|
|
133
|
-
|
|
134
|
-
const keys = Object.keys(payload);
|
|
135
|
-
if (keys.includes("status_list")) {
|
|
136
|
-
return import_ssi_types.StatusListType.OAuthStatusList;
|
|
137
|
-
} else if (keys.includes("vc")) {
|
|
138
|
-
return import_ssi_types.StatusListType.StatusList2021;
|
|
139
|
-
}
|
|
140
|
-
break;
|
|
144
|
+
return determineJwtStatusListType(credential);
|
|
141
145
|
case "lds":
|
|
142
|
-
|
|
143
|
-
const type = uniform.type.find((t) => {
|
|
144
|
-
return Object.values(import_ssi_types.StatusListType).some((statusType) => t.includes(statusType));
|
|
145
|
-
});
|
|
146
|
-
if (!type) {
|
|
147
|
-
throw new Error("Invalid status list credential type");
|
|
148
|
-
}
|
|
149
|
-
return type.replace("Credential", "");
|
|
146
|
+
return determineLdsStatusListType(credential);
|
|
150
147
|
case "cbor":
|
|
151
148
|
return import_ssi_types.StatusListType.OAuthStatusList;
|
|
149
|
+
default:
|
|
150
|
+
throw new Error("Cannot determine status list type from credential payload");
|
|
152
151
|
}
|
|
153
|
-
throw new Error("Cannot determine status list type from credential payload");
|
|
154
152
|
}
|
|
155
153
|
__name(determineStatusListType, "determineStatusListType");
|
|
154
|
+
function determineJwtStatusListType(credential) {
|
|
155
|
+
const payload = (0, import_jwt_decode.jwtDecode)(credential);
|
|
156
|
+
if ("status_list" in payload) {
|
|
157
|
+
return import_ssi_types.StatusListType.OAuthStatusList;
|
|
158
|
+
}
|
|
159
|
+
if ("credentialSubject" in payload) {
|
|
160
|
+
return getStatusListTypeFromSubject(payload.credentialSubject);
|
|
161
|
+
}
|
|
162
|
+
if ("vc" in payload && "credentialSubject" in payload.vc) {
|
|
163
|
+
return getStatusListTypeFromSubject(payload.vc.credentialSubject);
|
|
164
|
+
}
|
|
165
|
+
throw new Error("Invalid status list credential: credentialSubject not found");
|
|
166
|
+
}
|
|
167
|
+
__name(determineJwtStatusListType, "determineJwtStatusListType");
|
|
168
|
+
function determineLdsStatusListType(credential) {
|
|
169
|
+
const uniform = import_ssi_types.CredentialMapper.toUniformCredential(credential);
|
|
170
|
+
const statusListType = uniform.type.find((type) => Object.values(import_ssi_types.StatusListType).some((statusType) => type.includes(statusType)));
|
|
171
|
+
if (!statusListType) {
|
|
172
|
+
throw new Error("Invalid status list credential type");
|
|
173
|
+
}
|
|
174
|
+
return statusListType.replace("Credential", "");
|
|
175
|
+
}
|
|
176
|
+
__name(determineLdsStatusListType, "determineLdsStatusListType");
|
|
177
|
+
function getStatusListTypeFromSubject(credentialSubject) {
|
|
178
|
+
switch (credentialSubject.type) {
|
|
179
|
+
case "StatusList2021":
|
|
180
|
+
return import_ssi_types.StatusListType.StatusList2021;
|
|
181
|
+
case "BitstringStatusList":
|
|
182
|
+
return import_ssi_types.StatusListType.BitstringStatusList;
|
|
183
|
+
default:
|
|
184
|
+
throw new Error(`Unknown credential subject type: ${credentialSubject.type}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
__name(getStatusListTypeFromSubject, "getStatusListTypeFromSubject");
|
|
156
188
|
function determineProofFormat(credential) {
|
|
157
189
|
const type = import_ssi_types.CredentialMapper.detectDocumentType(credential);
|
|
158
190
|
switch (type) {
|
|
@@ -167,6 +199,26 @@ function determineProofFormat(credential) {
|
|
|
167
199
|
}
|
|
168
200
|
}
|
|
169
201
|
__name(determineProofFormat, "determineProofFormat");
|
|
202
|
+
function ensureDate(value) {
|
|
203
|
+
if (value === void 0 || value === null) {
|
|
204
|
+
return void 0;
|
|
205
|
+
}
|
|
206
|
+
if (value instanceof Date) {
|
|
207
|
+
return value;
|
|
208
|
+
}
|
|
209
|
+
if (typeof value === "string") {
|
|
210
|
+
if (value.trim() === "") {
|
|
211
|
+
return void 0;
|
|
212
|
+
}
|
|
213
|
+
const date = new Date(value);
|
|
214
|
+
if (isNaN(date.getTime())) {
|
|
215
|
+
return void 0;
|
|
216
|
+
}
|
|
217
|
+
return date;
|
|
218
|
+
}
|
|
219
|
+
return void 0;
|
|
220
|
+
}
|
|
221
|
+
__name(ensureDate, "ensureDate");
|
|
170
222
|
|
|
171
223
|
// src/impl/StatusList2021.ts
|
|
172
224
|
var import_ssi_types2 = require("@sphereon/ssi-types");
|
|
@@ -230,13 +282,14 @@ var StatusList2021Implementation = class {
|
|
|
230
282
|
encodedList,
|
|
231
283
|
proofFormat
|
|
232
284
|
}, context);
|
|
285
|
+
if (!("statusPurpose" in credentialSubject)) {
|
|
286
|
+
return Promise.reject(Error("statusPurpose is required in credentialSubject for StatusList2021"));
|
|
287
|
+
}
|
|
233
288
|
return {
|
|
234
289
|
statusListCredential: updatedCredential,
|
|
235
290
|
encodedList,
|
|
236
291
|
statusList2021: {
|
|
237
|
-
|
|
238
|
-
statusPurpose: credentialSubject.statusPurpose
|
|
239
|
-
} : {},
|
|
292
|
+
statusPurpose: credentialSubject.statusPurpose,
|
|
240
293
|
indexingDirection: "rightToLeft"
|
|
241
294
|
},
|
|
242
295
|
length: statusList.length - 1,
|
|
@@ -259,7 +312,7 @@ var StatusList2021Implementation = class {
|
|
|
259
312
|
encodedList: args.encodedList
|
|
260
313
|
});
|
|
261
314
|
const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
|
|
262
|
-
statusList.setStatus(index, args.value);
|
|
315
|
+
statusList.setStatus(index, args.value !== 0);
|
|
263
316
|
const newEncodedList = await statusList.encode();
|
|
264
317
|
const credential = await this.createVerifiableCredential({
|
|
265
318
|
id,
|
|
@@ -293,36 +346,88 @@ var StatusList2021Implementation = class {
|
|
|
293
346
|
const status = statusList.getStatus(typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex));
|
|
294
347
|
return status ? Status2021.Invalid : Status2021.Valid;
|
|
295
348
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
349
|
+
/**
|
|
350
|
+
* Performs the initial parsing of a StatusListCredential.
|
|
351
|
+
* This method handles expensive operations like JWT/CWT decoding once.
|
|
352
|
+
* It extracts all details available from the credential payload itself.
|
|
353
|
+
*/
|
|
354
|
+
async extractCredentialDetails(credential) {
|
|
355
|
+
const uniform = import_ssi_types2.CredentialMapper.toUniformCredential(credential);
|
|
299
356
|
const { issuer, credentialSubject } = uniform;
|
|
300
|
-
const
|
|
301
|
-
const encodedList = getAssertedProperty("encodedList", credentialSubject);
|
|
302
|
-
const proofFormat = import_ssi_types2.CredentialMapper.detectDocumentType(statusListPayload) === import_ssi_types2.DocumentFormat.JWT ? "jwt" : "lds";
|
|
303
|
-
const statusPurpose = getAssertedProperty("statusPurpose", credentialSubject);
|
|
304
|
-
const list = await import_vc_status_list.StatusList.decode({
|
|
305
|
-
encodedList
|
|
306
|
-
});
|
|
357
|
+
const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
307
358
|
return {
|
|
308
|
-
id,
|
|
309
|
-
encodedList,
|
|
359
|
+
id: getAssertedValue("id", uniform.id),
|
|
310
360
|
issuer,
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
361
|
+
encodedList: getAssertedProperty("encodedList", subject)
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
async toStatusListDetails(args) {
|
|
365
|
+
if ("statusListCredential" in args) {
|
|
366
|
+
const { statusListCredential, correlationId, driverType } = args;
|
|
367
|
+
const uniform = import_ssi_types2.CredentialMapper.toUniformCredential(statusListCredential);
|
|
368
|
+
const { issuer, credentialSubject } = uniform;
|
|
369
|
+
const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
370
|
+
const id = getAssertedValue("id", uniform.id);
|
|
371
|
+
const encodedList = getAssertedProperty("encodedList", subject);
|
|
372
|
+
const statusPurpose = getAssertedProperty("statusPurpose", subject);
|
|
373
|
+
const proofFormat = import_ssi_types2.CredentialMapper.detectDocumentType(statusListCredential) === import_ssi_types2.DocumentFormat.JWT ? "jwt" : "lds";
|
|
374
|
+
const list = await import_vc_status_list.StatusList.decode({
|
|
375
|
+
encodedList
|
|
376
|
+
});
|
|
377
|
+
return {
|
|
378
|
+
id,
|
|
379
|
+
encodedList,
|
|
380
|
+
issuer,
|
|
381
|
+
type: import_ssi_types2.StatusListType.StatusList2021,
|
|
382
|
+
proofFormat,
|
|
383
|
+
length: list.length,
|
|
384
|
+
statusListCredential,
|
|
385
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
386
|
+
correlationId,
|
|
387
|
+
driverType,
|
|
317
388
|
indexingDirection: "rightToLeft",
|
|
318
|
-
statusPurpose
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
389
|
+
statusPurpose,
|
|
390
|
+
statusList2021: {
|
|
391
|
+
indexingDirection: "rightToLeft",
|
|
392
|
+
statusPurpose
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
} else {
|
|
396
|
+
const { extractedDetails, statusListEntity } = args;
|
|
397
|
+
const statusList2021Entity = statusListEntity;
|
|
398
|
+
const proofFormat = import_ssi_types2.CredentialMapper.detectDocumentType(statusListEntity.statusListCredential) === import_ssi_types2.DocumentFormat.JWT ? "jwt" : "lds";
|
|
399
|
+
const list = await import_vc_status_list.StatusList.decode({
|
|
400
|
+
encodedList: extractedDetails.encodedList
|
|
401
|
+
});
|
|
402
|
+
return {
|
|
403
|
+
id: extractedDetails.id,
|
|
404
|
+
encodedList: extractedDetails.encodedList,
|
|
405
|
+
issuer: extractedDetails.issuer,
|
|
406
|
+
type: import_ssi_types2.StatusListType.StatusList2021,
|
|
407
|
+
proofFormat,
|
|
408
|
+
length: list.length,
|
|
409
|
+
statusListCredential: statusListEntity.statusListCredential,
|
|
410
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
411
|
+
correlationId: statusListEntity.correlationId,
|
|
412
|
+
driverType: statusListEntity.driverType,
|
|
413
|
+
indexingDirection: statusList2021Entity.indexingDirection,
|
|
414
|
+
statusPurpose: statusList2021Entity.statusPurpose,
|
|
415
|
+
statusList2021: {
|
|
416
|
+
indexingDirection: statusList2021Entity.indexingDirection,
|
|
417
|
+
statusPurpose: statusList2021Entity.statusPurpose
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
async createCredentialStatus(args) {
|
|
423
|
+
const { statusList, statusListIndex } = args;
|
|
424
|
+
const statusList2021 = statusList;
|
|
425
|
+
return {
|
|
426
|
+
id: `${statusList.id}#${statusListIndex}`,
|
|
427
|
+
type: "StatusList2021Entry",
|
|
428
|
+
statusPurpose: statusList2021.statusPurpose ?? "revocation",
|
|
429
|
+
statusListIndex: "" + statusListIndex,
|
|
430
|
+
statusListCredential: statusList.id
|
|
326
431
|
};
|
|
327
432
|
}
|
|
328
433
|
async createVerifiableCredential(args, context) {
|
|
@@ -617,7 +722,8 @@ var OAuthStatusListImplementation = class {
|
|
|
617
722
|
}
|
|
618
723
|
const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT2;
|
|
619
724
|
const { issuer, id, oauthStatusList, keyRef } = args;
|
|
620
|
-
const { bitsPerStatus
|
|
725
|
+
const { bitsPerStatus } = oauthStatusList;
|
|
726
|
+
const expiresAt = ensureDate(oauthStatusList.expiresAt);
|
|
621
727
|
const length = args.length ?? DEFAULT_LIST_LENGTH2;
|
|
622
728
|
const issuerString = typeof issuer === "string" ? issuer : issuer.id;
|
|
623
729
|
const correlationId = getAssertedValue("correlationId", args.correlationId);
|
|
@@ -640,7 +746,8 @@ var OAuthStatusListImplementation = class {
|
|
|
640
746
|
};
|
|
641
747
|
}
|
|
642
748
|
async updateStatusListIndex(args, context) {
|
|
643
|
-
const { statusListCredential, value,
|
|
749
|
+
const { statusListCredential, value, keyRef } = args;
|
|
750
|
+
const expiresAt = ensureDate(args.expiresAt);
|
|
644
751
|
if (typeof statusListCredential !== "string") {
|
|
645
752
|
return Promise.reject("statusListCredential in neither JWT nor CWT");
|
|
646
753
|
}
|
|
@@ -676,12 +783,13 @@ var OAuthStatusListImplementation = class {
|
|
|
676
783
|
throw new Error("OAuthStatusList options are required for type OAuthStatusList");
|
|
677
784
|
}
|
|
678
785
|
const { proofFormat, oauthStatusList, keyRef } = args;
|
|
679
|
-
const { bitsPerStatus
|
|
786
|
+
const { bitsPerStatus } = oauthStatusList;
|
|
787
|
+
const expiresAt = ensureDate(oauthStatusList.expiresAt);
|
|
680
788
|
const { issuer, id } = getAssertedValues(args);
|
|
681
789
|
const issuerString = typeof issuer === "string" ? issuer : issuer.id;
|
|
682
790
|
const listToUpdate = import_jwt_status_list3.StatusList.decompressStatusList(args.encodedList, bitsPerStatus ?? DEFAULT_BITS_PER_STATUS);
|
|
683
791
|
const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
|
|
684
|
-
listToUpdate.setStatus(index, args.value
|
|
792
|
+
listToUpdate.setStatus(index, args.value);
|
|
685
793
|
const { statusListCredential, encodedList } = await this.createSignedStatusList(proofFormat ?? DEFAULT_PROOF_FORMAT2, context, listToUpdate, issuerString, id, expiresAt, keyRef);
|
|
686
794
|
return {
|
|
687
795
|
encodedList,
|
|
@@ -698,9 +806,6 @@ var OAuthStatusListImplementation = class {
|
|
|
698
806
|
statuslistContentType: this.buildContentType(proofFormat)
|
|
699
807
|
};
|
|
700
808
|
}
|
|
701
|
-
buildContentType(proofFormat) {
|
|
702
|
-
return `application/statuslist+${proofFormat === "cbor" ? "cwt" : "jwt"}`;
|
|
703
|
-
}
|
|
704
809
|
async checkStatusIndex(args) {
|
|
705
810
|
const { statusListCredential, statusListIndex } = args;
|
|
706
811
|
if (typeof statusListCredential !== "string") {
|
|
@@ -714,34 +819,101 @@ var OAuthStatusListImplementation = class {
|
|
|
714
819
|
}
|
|
715
820
|
return statusList.getStatus(index);
|
|
716
821
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
822
|
+
/**
|
|
823
|
+
* Performs the initial parsing of a StatusListCredential.
|
|
824
|
+
* This method handles expensive operations like JWT/CWT decoding once.
|
|
825
|
+
* It extracts all details available from the credential payload itself.
|
|
826
|
+
*/
|
|
827
|
+
async extractCredentialDetails(credential) {
|
|
828
|
+
if (typeof credential !== "string") {
|
|
829
|
+
return Promise.reject("statusListCredential must be a JWT or CWT string");
|
|
830
|
+
}
|
|
831
|
+
const proofFormat = determineProofFormat(credential);
|
|
832
|
+
const decoded = proofFormat === "jwt" ? decodeStatusListJWT(credential) : decodeStatusListCWT(credential);
|
|
722
833
|
return {
|
|
723
|
-
id,
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
expiresAt: new Date(exp * 1e3)
|
|
735
|
-
}
|
|
736
|
-
},
|
|
737
|
-
...args.correlationId && {
|
|
738
|
-
correlationId: args.correlationId
|
|
739
|
-
},
|
|
740
|
-
...args.driverType && {
|
|
741
|
-
driverType: args.driverType
|
|
834
|
+
id: decoded.id,
|
|
835
|
+
issuer: decoded.issuer,
|
|
836
|
+
encodedList: decoded.statusList.compressStatusList(),
|
|
837
|
+
decodedPayload: decoded
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
async toStatusListDetails(args) {
|
|
841
|
+
if ("statusListCredential" in args) {
|
|
842
|
+
const { statusListCredential, bitsPerStatus, correlationId, driverType } = args;
|
|
843
|
+
if (!bitsPerStatus || bitsPerStatus < 1) {
|
|
844
|
+
return Promise.reject(Error("bitsPerStatus must be set for OAuth status lists and must be 1 or higher"));
|
|
742
845
|
}
|
|
846
|
+
const proofFormat = determineProofFormat(statusListCredential);
|
|
847
|
+
const decoded = proofFormat === "jwt" ? decodeStatusListJWT(statusListCredential) : decodeStatusListCWT(statusListCredential);
|
|
848
|
+
const { statusList, issuer, id, exp } = decoded;
|
|
849
|
+
const expiresAt = exp ? new Date(exp * 1e3) : void 0;
|
|
850
|
+
return {
|
|
851
|
+
id,
|
|
852
|
+
encodedList: statusList.compressStatusList(),
|
|
853
|
+
issuer,
|
|
854
|
+
type: import_ssi_types4.StatusListType.OAuthStatusList,
|
|
855
|
+
proofFormat,
|
|
856
|
+
length: statusList.statusList.length,
|
|
857
|
+
statusListCredential,
|
|
858
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
859
|
+
correlationId,
|
|
860
|
+
driverType,
|
|
861
|
+
bitsPerStatus,
|
|
862
|
+
...expiresAt && {
|
|
863
|
+
expiresAt
|
|
864
|
+
},
|
|
865
|
+
oauthStatusList: {
|
|
866
|
+
bitsPerStatus,
|
|
867
|
+
...expiresAt && {
|
|
868
|
+
expiresAt
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
} else {
|
|
873
|
+
const { extractedDetails, statusListEntity } = args;
|
|
874
|
+
const oauthEntity = statusListEntity;
|
|
875
|
+
const decoded = extractedDetails.decodedPayload;
|
|
876
|
+
const proofFormat = determineProofFormat(statusListEntity.statusListCredential);
|
|
877
|
+
const expiresAt = decoded.exp ? new Date(decoded.exp * 1e3) : void 0;
|
|
878
|
+
return {
|
|
879
|
+
id: extractedDetails.id,
|
|
880
|
+
encodedList: extractedDetails.encodedList,
|
|
881
|
+
issuer: extractedDetails.issuer,
|
|
882
|
+
type: import_ssi_types4.StatusListType.OAuthStatusList,
|
|
883
|
+
proofFormat,
|
|
884
|
+
length: decoded.statusList.statusList.length,
|
|
885
|
+
statusListCredential: statusListEntity.statusListCredential,
|
|
886
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
887
|
+
correlationId: statusListEntity.correlationId,
|
|
888
|
+
driverType: statusListEntity.driverType,
|
|
889
|
+
bitsPerStatus: oauthEntity.bitsPerStatus,
|
|
890
|
+
...expiresAt && {
|
|
891
|
+
expiresAt
|
|
892
|
+
},
|
|
893
|
+
oauthStatusList: {
|
|
894
|
+
bitsPerStatus: oauthEntity.bitsPerStatus,
|
|
895
|
+
...expiresAt && {
|
|
896
|
+
expiresAt
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
async createCredentialStatus(args) {
|
|
903
|
+
const { statusList, statusListIndex } = args;
|
|
904
|
+
const oauthStatusList = statusList;
|
|
905
|
+
return {
|
|
906
|
+
id: `${statusList.id}#${statusListIndex}`,
|
|
907
|
+
type: "OAuthStatusListEntry",
|
|
908
|
+
bitsPerStatus: oauthStatusList.bitsPerStatus,
|
|
909
|
+
statusListIndex: "" + statusListIndex,
|
|
910
|
+
statusListCredential: statusList.id,
|
|
911
|
+
expiresAt: oauthStatusList.expiresAt
|
|
743
912
|
};
|
|
744
913
|
}
|
|
914
|
+
buildContentType(proofFormat) {
|
|
915
|
+
return `application/statuslist+${proofFormat === "cbor" ? "cwt" : "jwt"}`;
|
|
916
|
+
}
|
|
745
917
|
async createSignedStatusList(proofFormat, context, statusList, issuerString, id, expiresAt, keyRef) {
|
|
746
918
|
switch (proofFormat) {
|
|
747
919
|
case "jwt": {
|
|
@@ -761,15 +933,21 @@ var import_ssi_types6 = require("@sphereon/ssi-types");
|
|
|
761
933
|
|
|
762
934
|
// src/impl/BitstringStatusListImplementation.ts
|
|
763
935
|
var import_ssi_types5 = require("@sphereon/ssi-types");
|
|
764
|
-
var
|
|
936
|
+
var import_vc_bitstring_status_lists = require("@4sure-tech/vc-bitstring-status-lists");
|
|
765
937
|
var DEFAULT_LIST_LENGTH3 = 131072;
|
|
766
|
-
var DEFAULT_PROOF_FORMAT3 = "
|
|
767
|
-
var DEFAULT_STATUS_SIZE = 1;
|
|
938
|
+
var DEFAULT_PROOF_FORMAT3 = "vc+jwt";
|
|
768
939
|
var DEFAULT_STATUS_PURPOSE = "revocation";
|
|
769
940
|
var BitstringStatusListImplementation = class {
|
|
770
941
|
static {
|
|
771
942
|
__name(this, "BitstringStatusListImplementation");
|
|
772
943
|
}
|
|
944
|
+
/**
|
|
945
|
+
* Creates a new bitstring status list with the specified configuration
|
|
946
|
+
*
|
|
947
|
+
* @param args - Configuration for the new status list including issuer, purpose, and size
|
|
948
|
+
* @param context - Veramo agent context for credential operations
|
|
949
|
+
* @returns Promise resolving to the created status list details
|
|
950
|
+
*/
|
|
773
951
|
async createNewStatusList(args, context) {
|
|
774
952
|
if (!args.bitstringStatusList) {
|
|
775
953
|
throw new Error("BitstringStatusList options are required for type BitstringStatusList");
|
|
@@ -777,29 +955,37 @@ var BitstringStatusListImplementation = class {
|
|
|
777
955
|
const length = args?.length ?? DEFAULT_LIST_LENGTH3;
|
|
778
956
|
const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT3;
|
|
779
957
|
assertValidProofType(import_ssi_types5.StatusListType.BitstringStatusList, proofFormat);
|
|
780
|
-
const veramoProofFormat = proofFormat;
|
|
781
958
|
const { issuer, id } = args;
|
|
782
959
|
const correlationId = getAssertedValue("correlationId", args.correlationId);
|
|
783
|
-
const { statusPurpose,
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
const encodedList = await list.encode();
|
|
788
|
-
const statusListCredential = await this.createVerifiableCredential({
|
|
789
|
-
...args,
|
|
790
|
-
encodedList,
|
|
791
|
-
proofFormat: veramoProofFormat,
|
|
960
|
+
const { statusPurpose, bitsPerStatus, validFrom, validUntil, ttl } = args.bitstringStatusList;
|
|
961
|
+
const unsignedCredential = await (0, import_vc_bitstring_status_lists.createStatusListCredential)({
|
|
962
|
+
id,
|
|
963
|
+
issuer,
|
|
792
964
|
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
793
|
-
|
|
794
|
-
|
|
965
|
+
validFrom: ensureDate(validFrom),
|
|
966
|
+
validUntil: ensureDate(validUntil),
|
|
795
967
|
ttl
|
|
968
|
+
});
|
|
969
|
+
const statusListCredential = await this.createVerifiableCredential({
|
|
970
|
+
unsignedCredential,
|
|
971
|
+
id,
|
|
972
|
+
issuer,
|
|
973
|
+
proofFormat,
|
|
974
|
+
keyRef: args.keyRef
|
|
796
975
|
}, context);
|
|
797
976
|
return {
|
|
798
|
-
encodedList,
|
|
977
|
+
encodedList: unsignedCredential.credentialSubject.encodedList,
|
|
799
978
|
statusListCredential,
|
|
800
979
|
bitstringStatusList: {
|
|
801
980
|
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
802
|
-
|
|
981
|
+
...unsignedCredential.validFrom && {
|
|
982
|
+
validFrom: new Date(unsignedCredential.validFrom)
|
|
983
|
+
},
|
|
984
|
+
...unsignedCredential.validUntil && {
|
|
985
|
+
validUntil: new Date(unsignedCredential.validUntil)
|
|
986
|
+
},
|
|
987
|
+
ttl,
|
|
988
|
+
bitsPerStatus
|
|
803
989
|
},
|
|
804
990
|
length,
|
|
805
991
|
type: import_ssi_types5.StatusListType.BitstringStatusList,
|
|
@@ -810,45 +996,66 @@ var BitstringStatusListImplementation = class {
|
|
|
810
996
|
statuslistContentType: this.buildContentType(proofFormat)
|
|
811
997
|
};
|
|
812
998
|
}
|
|
999
|
+
/**
|
|
1000
|
+
* Updates the status of a specific credential in an existing status list
|
|
1001
|
+
*
|
|
1002
|
+
* @param args - Update parameters including the status list credential, index, and new value
|
|
1003
|
+
* @param context - Veramo agent context for credential operations
|
|
1004
|
+
* @returns Promise resolving to the updated status list details
|
|
1005
|
+
*/
|
|
813
1006
|
async updateStatusListIndex(args, context) {
|
|
1007
|
+
if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
|
|
1008
|
+
return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListIndex)"));
|
|
1009
|
+
}
|
|
814
1010
|
const credential = args.statusListCredential;
|
|
815
1011
|
const uniform = import_ssi_types5.CredentialMapper.toUniformCredential(credential);
|
|
816
1012
|
const { issuer, credentialSubject } = uniform;
|
|
817
1013
|
const id = getAssertedValue("id", uniform.id);
|
|
818
1014
|
const origEncodedList = getAssertedProperty("encodedList", credentialSubject);
|
|
819
1015
|
const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
|
|
820
|
-
const statusList = await
|
|
821
|
-
encodedList: origEncodedList
|
|
1016
|
+
const statusList = await import_vc_bitstring_status_lists.BitstreamStatusList.decode({
|
|
1017
|
+
encodedList: origEncodedList,
|
|
1018
|
+
statusSize: args.bitsPerStatus
|
|
822
1019
|
});
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
const proofFormat = import_ssi_types5.CredentialMapper.detectDocumentType(credential) === import_ssi_types5.DocumentFormat.JWT ? "jwt" : "lds";
|
|
1020
|
+
const bitstringStatusId = args.value;
|
|
1021
|
+
statusList.setStatus(index, bitstringStatusId);
|
|
1022
|
+
const proofFormat = import_ssi_types5.CredentialMapper.detectDocumentType(credential) === import_ssi_types5.DocumentFormat.JWT ? "vc+jwt" : "lds";
|
|
826
1023
|
const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
827
1024
|
const statusPurpose = getAssertedProperty("statusPurpose", credSubject);
|
|
828
1025
|
const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : void 0;
|
|
829
1026
|
const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : void 0;
|
|
830
1027
|
const ttl = credSubject.ttl;
|
|
1028
|
+
const unsignedCredential = await (0, import_vc_bitstring_status_lists.createStatusListCredential)({
|
|
1029
|
+
id,
|
|
1030
|
+
issuer,
|
|
1031
|
+
statusList,
|
|
1032
|
+
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
1033
|
+
validFrom: ensureDate(validFrom),
|
|
1034
|
+
validUntil: ensureDate(validUntil),
|
|
1035
|
+
ttl
|
|
1036
|
+
});
|
|
831
1037
|
const updatedCredential = await this.createVerifiableCredential({
|
|
832
|
-
|
|
1038
|
+
unsignedCredential,
|
|
833
1039
|
id,
|
|
834
1040
|
issuer,
|
|
835
|
-
encodedList,
|
|
836
1041
|
proofFormat,
|
|
837
|
-
|
|
838
|
-
ttl,
|
|
839
|
-
validFrom,
|
|
840
|
-
validUntil
|
|
1042
|
+
keyRef: args.keyRef
|
|
841
1043
|
}, context);
|
|
842
1044
|
return {
|
|
843
1045
|
statusListCredential: updatedCredential,
|
|
844
|
-
encodedList,
|
|
1046
|
+
encodedList: unsignedCredential.credentialSubject.encodedList,
|
|
845
1047
|
bitstringStatusList: {
|
|
846
1048
|
statusPurpose,
|
|
847
|
-
validFrom
|
|
848
|
-
|
|
1049
|
+
...unsignedCredential.validFrom && {
|
|
1050
|
+
validFrom: new Date(unsignedCredential.validFrom)
|
|
1051
|
+
},
|
|
1052
|
+
...unsignedCredential.validUntil && {
|
|
1053
|
+
validUntil: new Date(unsignedCredential.validUntil)
|
|
1054
|
+
},
|
|
1055
|
+
bitsPerStatus: args.bitsPerStatus,
|
|
849
1056
|
ttl
|
|
850
1057
|
},
|
|
851
|
-
length: statusList.
|
|
1058
|
+
length: statusList.getLength(),
|
|
852
1059
|
type: import_ssi_types5.StatusListType.BitstringStatusList,
|
|
853
1060
|
proofFormat,
|
|
854
1061
|
id,
|
|
@@ -856,166 +1063,262 @@ var BitstringStatusListImplementation = class {
|
|
|
856
1063
|
statuslistContentType: this.buildContentType(proofFormat)
|
|
857
1064
|
};
|
|
858
1065
|
}
|
|
1066
|
+
/**
|
|
1067
|
+
* Updates a status list by decoding an encoded list, modifying it, and re-encoding
|
|
1068
|
+
*
|
|
1069
|
+
* @param args - Update parameters including encoded list, index, and new value
|
|
1070
|
+
* @param context - Veramo agent context for credential operations
|
|
1071
|
+
* @returns Promise resolving to the updated status list details
|
|
1072
|
+
*/
|
|
859
1073
|
async updateStatusListFromEncodedList(args, context) {
|
|
860
1074
|
if (!args.bitstringStatusList) {
|
|
861
1075
|
throw new Error("bitstringStatusList options required for type BitstringStatusList");
|
|
862
1076
|
}
|
|
1077
|
+
if (args.bitstringStatusList.bitsPerStatus < 1) {
|
|
1078
|
+
return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListFromEncodedList)"));
|
|
1079
|
+
}
|
|
1080
|
+
const { statusPurpose, bitsPerStatus, ttl, validFrom, validUntil } = args.bitstringStatusList;
|
|
863
1081
|
const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT3;
|
|
864
1082
|
assertValidProofType(import_ssi_types5.StatusListType.BitstringStatusList, proofFormat);
|
|
865
|
-
const veramoProofFormat = proofFormat;
|
|
866
1083
|
const { issuer, id } = getAssertedValues(args);
|
|
867
|
-
const statusList = await
|
|
868
|
-
encodedList: args.encodedList
|
|
1084
|
+
const statusList = await import_vc_bitstring_status_lists.BitstreamStatusList.decode({
|
|
1085
|
+
encodedList: args.encodedList,
|
|
1086
|
+
statusSize: bitsPerStatus
|
|
869
1087
|
});
|
|
870
1088
|
const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
|
|
871
1089
|
statusList.setStatus(index, args.value);
|
|
872
|
-
const
|
|
873
|
-
const { statusPurpose, statusSize, statusMessage, ttl, validFrom, validUntil } = args.bitstringStatusList;
|
|
874
|
-
const credential = await this.createVerifiableCredential({
|
|
1090
|
+
const unsignedCredential = await (0, import_vc_bitstring_status_lists.createStatusListCredential)({
|
|
875
1091
|
id,
|
|
876
1092
|
issuer,
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
statusSize,
|
|
882
|
-
statusMessage,
|
|
883
|
-
validFrom,
|
|
884
|
-
validUntil,
|
|
1093
|
+
statusList,
|
|
1094
|
+
statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
|
|
1095
|
+
validFrom: ensureDate(validFrom),
|
|
1096
|
+
validUntil: ensureDate(validUntil),
|
|
885
1097
|
ttl
|
|
1098
|
+
});
|
|
1099
|
+
const credential = await this.createVerifiableCredential({
|
|
1100
|
+
unsignedCredential,
|
|
1101
|
+
id,
|
|
1102
|
+
issuer,
|
|
1103
|
+
proofFormat,
|
|
1104
|
+
keyRef: args.keyRef
|
|
886
1105
|
}, context);
|
|
887
1106
|
return {
|
|
888
1107
|
type: import_ssi_types5.StatusListType.BitstringStatusList,
|
|
889
1108
|
statusListCredential: credential,
|
|
890
|
-
encodedList:
|
|
1109
|
+
encodedList: unsignedCredential.credentialSubject.encodedList,
|
|
891
1110
|
bitstringStatusList: {
|
|
892
1111
|
statusPurpose,
|
|
893
|
-
|
|
894
|
-
|
|
1112
|
+
bitsPerStatus,
|
|
1113
|
+
...unsignedCredential.validFrom && {
|
|
1114
|
+
validFrom: new Date(unsignedCredential.validFrom)
|
|
1115
|
+
},
|
|
1116
|
+
...unsignedCredential.validUntil && {
|
|
1117
|
+
validUntil: new Date(unsignedCredential.validUntil)
|
|
1118
|
+
},
|
|
895
1119
|
ttl
|
|
896
1120
|
},
|
|
897
|
-
length: statusList.
|
|
1121
|
+
length: statusList.getLength(),
|
|
898
1122
|
proofFormat: args.proofFormat ?? "lds",
|
|
899
1123
|
id,
|
|
900
1124
|
issuer,
|
|
901
1125
|
statuslistContentType: this.buildContentType(proofFormat)
|
|
902
1126
|
};
|
|
903
1127
|
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Checks the status of a specific credential by its index in the status list
|
|
1130
|
+
*
|
|
1131
|
+
* @param args - Check parameters including the status list credential and index
|
|
1132
|
+
* @returns Promise resolving to the status value at the specified index
|
|
1133
|
+
*/
|
|
904
1134
|
async checkStatusIndex(args) {
|
|
1135
|
+
if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
|
|
1136
|
+
return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (checkStatusIndex)"));
|
|
1137
|
+
}
|
|
905
1138
|
const uniform = import_ssi_types5.CredentialMapper.toUniformCredential(args.statusListCredential);
|
|
906
1139
|
const { credentialSubject } = uniform;
|
|
907
1140
|
const encodedList = getAssertedProperty("encodedList", credentialSubject);
|
|
908
|
-
const
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
const hexIndex = `0x${numIndex.toString(16)}`;
|
|
912
|
-
const statusMessage = messageList.find((statMsg) => statMsg.status === hexIndex);
|
|
913
|
-
const statusList = await (0, import_vc_bitstring_status_list.decodeList)({
|
|
914
|
-
encodedList
|
|
1141
|
+
const statusList = await import_vc_bitstring_status_lists.BitstreamStatusList.decode({
|
|
1142
|
+
encodedList,
|
|
1143
|
+
statusSize: args.bitsPerStatus
|
|
915
1144
|
});
|
|
916
|
-
|
|
917
|
-
|
|
1145
|
+
const numIndex = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
|
|
1146
|
+
if (statusList.getLength() <= numIndex) {
|
|
1147
|
+
throw new Error(`Status list index out of bounds, has ${statusList.getLength()} entries, requested ${numIndex}`);
|
|
918
1148
|
}
|
|
919
|
-
|
|
920
|
-
return {
|
|
921
|
-
index: numIndex,
|
|
922
|
-
status: hexIndex,
|
|
923
|
-
message: statusMessage?.message,
|
|
924
|
-
set: value
|
|
925
|
-
};
|
|
1149
|
+
return statusList.getStatus(numIndex);
|
|
926
1150
|
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
1151
|
+
/**
|
|
1152
|
+
* Performs the initial parsing of a StatusListCredential.
|
|
1153
|
+
* This method handles expensive operations like JWT/CWT decoding once.
|
|
1154
|
+
* It extracts all details available from the credential payload itself.
|
|
1155
|
+
*/
|
|
1156
|
+
async extractCredentialDetails(credential) {
|
|
1157
|
+
const uniform = import_ssi_types5.CredentialMapper.toUniformCredential(credential);
|
|
930
1158
|
const { issuer, credentialSubject } = uniform;
|
|
931
|
-
const
|
|
932
|
-
const encodedList = getAssertedProperty("encodedList", credentialSubject);
|
|
933
|
-
const proofFormat = import_ssi_types5.CredentialMapper.detectDocumentType(statusListPayload) === import_ssi_types5.DocumentFormat.JWT ? "jwt" : "lds";
|
|
934
|
-
const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
935
|
-
const statusPurpose = getAssertedProperty("statusPurpose", credSubject);
|
|
936
|
-
const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : void 0;
|
|
937
|
-
const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : void 0;
|
|
938
|
-
const ttl = credSubject.ttl;
|
|
939
|
-
const list = await (0, import_vc_bitstring_status_list.decodeList)({
|
|
940
|
-
encodedList
|
|
941
|
-
});
|
|
1159
|
+
const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
942
1160
|
return {
|
|
943
|
-
id,
|
|
944
|
-
encodedList,
|
|
1161
|
+
id: getAssertedValue("id", uniform.id),
|
|
945
1162
|
issuer,
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
1163
|
+
encodedList: getAssertedProperty("encodedList", subject)
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
async toStatusListDetails(args) {
|
|
1167
|
+
if ("statusListCredential" in args) {
|
|
1168
|
+
const { statusListCredential, bitsPerStatus, correlationId, driverType } = args;
|
|
1169
|
+
if (!bitsPerStatus || bitsPerStatus < 1) {
|
|
1170
|
+
return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher"));
|
|
1171
|
+
}
|
|
1172
|
+
const uniform = import_ssi_types5.CredentialMapper.toUniformCredential(statusListCredential);
|
|
1173
|
+
const { issuer, credentialSubject } = uniform;
|
|
1174
|
+
const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
|
|
1175
|
+
const id = getAssertedValue("id", uniform.id);
|
|
1176
|
+
const encodedList = getAssertedProperty("encodedList", subject);
|
|
1177
|
+
const statusPurpose = getAssertedProperty("statusPurpose", subject);
|
|
1178
|
+
const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : void 0;
|
|
1179
|
+
const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : void 0;
|
|
1180
|
+
const ttl = subject.ttl;
|
|
1181
|
+
const proofFormat = import_ssi_types5.CredentialMapper.detectDocumentType(statusListCredential) === import_ssi_types5.DocumentFormat.JWT ? "vc+jwt" : "lds";
|
|
1182
|
+
const statuslistLength = import_vc_bitstring_status_lists.BitstreamStatusList.getStatusListLength(encodedList, bitsPerStatus);
|
|
1183
|
+
return {
|
|
1184
|
+
id,
|
|
1185
|
+
encodedList,
|
|
1186
|
+
issuer,
|
|
1187
|
+
type: import_ssi_types5.StatusListType.BitstringStatusList,
|
|
1188
|
+
proofFormat,
|
|
1189
|
+
length: statuslistLength,
|
|
1190
|
+
statusListCredential,
|
|
1191
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
1192
|
+
correlationId,
|
|
1193
|
+
driverType,
|
|
952
1194
|
statusPurpose,
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
1195
|
+
bitsPerStatus,
|
|
1196
|
+
...validFrom && {
|
|
1197
|
+
validFrom
|
|
1198
|
+
},
|
|
1199
|
+
...validUntil && {
|
|
1200
|
+
validUntil
|
|
1201
|
+
},
|
|
1202
|
+
...ttl && {
|
|
1203
|
+
ttl
|
|
1204
|
+
},
|
|
1205
|
+
bitstringStatusList: {
|
|
1206
|
+
statusPurpose,
|
|
1207
|
+
bitsPerStatus,
|
|
1208
|
+
...validFrom && {
|
|
1209
|
+
validFrom
|
|
1210
|
+
},
|
|
1211
|
+
...validUntil && {
|
|
1212
|
+
validUntil
|
|
1213
|
+
},
|
|
1214
|
+
...ttl && {
|
|
1215
|
+
ttl
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
};
|
|
1219
|
+
} else {
|
|
1220
|
+
const { extractedDetails, statusListEntity } = args;
|
|
1221
|
+
const bitstringEntity = statusListEntity;
|
|
1222
|
+
if (!bitstringEntity.bitsPerStatus) {
|
|
1223
|
+
return Promise.reject(Error("bitsPerStatus must be present for a bitstring status list"));
|
|
962
1224
|
}
|
|
1225
|
+
const proofFormat = import_ssi_types5.CredentialMapper.detectDocumentType(statusListEntity.statusListCredential) === import_ssi_types5.DocumentFormat.JWT ? "vc+jwt" : "lds";
|
|
1226
|
+
const statuslistLength = import_vc_bitstring_status_lists.BitstreamStatusList.getStatusListLength(extractedDetails.encodedList, bitstringEntity.bitsPerStatus);
|
|
1227
|
+
return {
|
|
1228
|
+
id: extractedDetails.id,
|
|
1229
|
+
encodedList: extractedDetails.encodedList,
|
|
1230
|
+
issuer: extractedDetails.issuer,
|
|
1231
|
+
type: import_ssi_types5.StatusListType.BitstringStatusList,
|
|
1232
|
+
proofFormat,
|
|
1233
|
+
length: statuslistLength,
|
|
1234
|
+
statusListCredential: statusListEntity.statusListCredential,
|
|
1235
|
+
statuslistContentType: this.buildContentType(proofFormat),
|
|
1236
|
+
correlationId: statusListEntity.correlationId,
|
|
1237
|
+
driverType: statusListEntity.driverType,
|
|
1238
|
+
statusPurpose: bitstringEntity.statusPurpose,
|
|
1239
|
+
bitsPerStatus: bitstringEntity.bitsPerStatus,
|
|
1240
|
+
...bitstringEntity.validFrom && {
|
|
1241
|
+
validFrom: bitstringEntity.validFrom
|
|
1242
|
+
},
|
|
1243
|
+
...bitstringEntity.validUntil && {
|
|
1244
|
+
validUntil: bitstringEntity.validUntil
|
|
1245
|
+
},
|
|
1246
|
+
...bitstringEntity.ttl && {
|
|
1247
|
+
ttl: bitstringEntity.ttl
|
|
1248
|
+
},
|
|
1249
|
+
bitstringStatusList: {
|
|
1250
|
+
statusPurpose: bitstringEntity.statusPurpose,
|
|
1251
|
+
bitsPerStatus: bitstringEntity.bitsPerStatus,
|
|
1252
|
+
...bitstringEntity.validFrom && {
|
|
1253
|
+
validFrom: bitstringEntity.validFrom
|
|
1254
|
+
},
|
|
1255
|
+
...bitstringEntity.validUntil && {
|
|
1256
|
+
validUntil: bitstringEntity.validUntil
|
|
1257
|
+
},
|
|
1258
|
+
...bitstringEntity.ttl && {
|
|
1259
|
+
ttl: bitstringEntity.ttl
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
};
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
/**
|
|
1266
|
+
* Creates a credential status entry for a specific credential in a status list
|
|
1267
|
+
*
|
|
1268
|
+
* @param args - Parameters including the status list, entry details, and index
|
|
1269
|
+
* @returns Promise resolving to the credential status entry
|
|
1270
|
+
*/
|
|
1271
|
+
async createCredentialStatus(args) {
|
|
1272
|
+
const { statusList, statusListEntry, statusListIndex } = args;
|
|
1273
|
+
const bitstringStatusList = statusList;
|
|
1274
|
+
const bitstringStatusListEntry = statusListEntry;
|
|
1275
|
+
return {
|
|
1276
|
+
id: `${statusList.id}#${statusListIndex}`,
|
|
1277
|
+
type: "BitstringStatusListEntry",
|
|
1278
|
+
statusPurpose: bitstringStatusListEntry.statusPurpose,
|
|
1279
|
+
statusListIndex: "" + statusListIndex,
|
|
1280
|
+
statusListCredential: statusList.id,
|
|
1281
|
+
bitsPerStatus: bitstringStatusList.bitsPerStatus,
|
|
1282
|
+
statusMessage: bitstringStatusListEntry.statusMessage,
|
|
1283
|
+
statusReference: bitstringStatusListEntry.statusReference
|
|
963
1284
|
};
|
|
964
1285
|
}
|
|
1286
|
+
/**
|
|
1287
|
+
* Creates a signed verifiable credential from an unsigned status list credential
|
|
1288
|
+
*
|
|
1289
|
+
* @param args - Parameters including the unsigned credential and signing details
|
|
1290
|
+
* @param context - Veramo agent context for credential operations
|
|
1291
|
+
* @returns Promise resolving to the signed credential
|
|
1292
|
+
*/
|
|
965
1293
|
async createVerifiableCredential(args, context) {
|
|
1294
|
+
const { unsignedCredential, issuer, proofFormat, keyRef } = args;
|
|
966
1295
|
const identifier = await context.agent.identifierManagedGet({
|
|
967
|
-
identifier: typeof
|
|
1296
|
+
identifier: typeof issuer === "string" ? issuer : issuer.id,
|
|
968
1297
|
vmRelationship: "assertionMethod",
|
|
969
1298
|
offlineWhenNoDIDRegistered: true
|
|
970
1299
|
});
|
|
971
|
-
const credentialSubject = {
|
|
972
|
-
id: args.id,
|
|
973
|
-
type: "BitstringStatusList",
|
|
974
|
-
statusPurpose: args.statusPurpose,
|
|
975
|
-
encodedList: args.encodedList
|
|
976
|
-
};
|
|
977
|
-
if (args.statusSize && args.statusSize > 1) {
|
|
978
|
-
credentialSubject.statusSize = args.statusSize;
|
|
979
|
-
}
|
|
980
|
-
if (args.statusMessage) {
|
|
981
|
-
credentialSubject.statusMessage = args.statusMessage;
|
|
982
|
-
}
|
|
983
|
-
if (args.validFrom) {
|
|
984
|
-
credentialSubject.validFrom = args.validFrom;
|
|
985
|
-
}
|
|
986
|
-
if (args.validUntil) {
|
|
987
|
-
credentialSubject.validUntil = args.validUntil;
|
|
988
|
-
}
|
|
989
|
-
if (args.ttl) {
|
|
990
|
-
credentialSubject.ttl = args.ttl;
|
|
991
|
-
}
|
|
992
|
-
const credential = {
|
|
993
|
-
"@context": [
|
|
994
|
-
"https://www.w3.org/2018/credentials/v1",
|
|
995
|
-
"https://www.w3.org/ns/credentials/status/v1"
|
|
996
|
-
],
|
|
997
|
-
id: args.id,
|
|
998
|
-
issuer: args.issuer,
|
|
999
|
-
type: [
|
|
1000
|
-
"VerifiableCredential",
|
|
1001
|
-
"BitstringStatusListCredential"
|
|
1002
|
-
],
|
|
1003
|
-
credentialSubject
|
|
1004
|
-
};
|
|
1005
1300
|
const verifiableCredential = await context.agent.createVerifiableCredential({
|
|
1006
|
-
credential,
|
|
1007
|
-
keyRef:
|
|
1008
|
-
proofFormat
|
|
1301
|
+
credential: unsignedCredential,
|
|
1302
|
+
keyRef: keyRef ?? identifier.kmsKeyRef,
|
|
1303
|
+
proofFormat,
|
|
1009
1304
|
fetchRemoteContexts: true
|
|
1010
1305
|
});
|
|
1011
1306
|
return import_ssi_types5.CredentialMapper.toWrappedVerifiableCredential(verifiableCredential).original;
|
|
1012
1307
|
}
|
|
1308
|
+
/**
|
|
1309
|
+
* Builds the appropriate content type string for a given proof format
|
|
1310
|
+
*
|
|
1311
|
+
* @param proofFormat - The proof format to build content type for
|
|
1312
|
+
* @returns The corresponding content type string
|
|
1313
|
+
*/
|
|
1013
1314
|
buildContentType(proofFormat) {
|
|
1014
1315
|
switch (proofFormat) {
|
|
1015
1316
|
case "jwt":
|
|
1016
|
-
return
|
|
1317
|
+
return "application/statuslist+jwt";
|
|
1017
1318
|
case "cbor":
|
|
1018
|
-
return
|
|
1319
|
+
return "application/statuslist+cwt";
|
|
1320
|
+
case "vc+jwt":
|
|
1321
|
+
return "application/statuslist+vc+jwt";
|
|
1019
1322
|
case "lds":
|
|
1020
1323
|
return "application/statuslist+ld+json";
|
|
1021
1324
|
default:
|
|
@@ -1171,35 +1474,35 @@ async function updateStatusIndexFromStatusListCredential(args, context) {
|
|
|
1171
1474
|
return implementation.updateStatusListIndex(args, context);
|
|
1172
1475
|
}
|
|
1173
1476
|
__name(updateStatusIndexFromStatusListCredential, "updateStatusIndexFromStatusListCredential");
|
|
1174
|
-
async function
|
|
1175
|
-
const
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
const type = uniform.type.find((t) => t.includes("StatusList2021") || t.includes("OAuth2StatusList") || t.includes("BitstringStatusList"));
|
|
1190
|
-
if (!type) {
|
|
1191
|
-
throw new Error("Invalid status list credential type");
|
|
1192
|
-
}
|
|
1193
|
-
statusListType = type.replace("Credential", "");
|
|
1477
|
+
async function extractCredentialDetails(statusListCredential) {
|
|
1478
|
+
const statusListType = determineStatusListType(statusListCredential);
|
|
1479
|
+
const implementation = getStatusListImplementation(statusListType);
|
|
1480
|
+
return implementation.extractCredentialDetails(statusListCredential);
|
|
1481
|
+
}
|
|
1482
|
+
__name(extractCredentialDetails, "extractCredentialDetails");
|
|
1483
|
+
async function toStatusListDetails(args) {
|
|
1484
|
+
if ("statusListCredential" in args) {
|
|
1485
|
+
const statusListType = args.statusListType;
|
|
1486
|
+
const implementation = getStatusListImplementation(statusListType);
|
|
1487
|
+
return implementation.toStatusListDetails(args);
|
|
1488
|
+
} else {
|
|
1489
|
+
const statusListType = args.statusListEntity.type;
|
|
1490
|
+
const implementation = getStatusListImplementation(statusListType);
|
|
1491
|
+
return implementation.toStatusListDetails(args);
|
|
1194
1492
|
}
|
|
1493
|
+
}
|
|
1494
|
+
__name(toStatusListDetails, "toStatusListDetails");
|
|
1495
|
+
async function createCredentialStatusFromStatusList(args) {
|
|
1496
|
+
const { statusList, statusListEntry, statusListIndex } = args;
|
|
1497
|
+
const statusListType = determineStatusListType(statusList.statusListCredential);
|
|
1195
1498
|
const implementation = getStatusListImplementation(statusListType);
|
|
1196
|
-
return
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1499
|
+
return implementation.createCredentialStatus({
|
|
1500
|
+
statusList,
|
|
1501
|
+
statusListEntry,
|
|
1502
|
+
statusListIndex
|
|
1200
1503
|
});
|
|
1201
1504
|
}
|
|
1202
|
-
__name(
|
|
1505
|
+
__name(createCredentialStatusFromStatusList, "createCredentialStatusFromStatusList");
|
|
1203
1506
|
async function updateStatusListIndexFromEncodedList(args, context) {
|
|
1204
1507
|
const { type } = getAssertedValue("type", args);
|
|
1205
1508
|
const implementation = getStatusListImplementation(type);
|