@sphereon/ssi-sdk.vc-status-list 0.34.1-feature.SSISDK.17.bitstring.sl.8 → 0.34.1-feature.SSISDK.26.48

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 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
@@ -122,7 +125,8 @@ var ValidProofTypeMap = /* @__PURE__ */ new Map([
122
125
  [
123
126
  import_ssi_types.StatusListType.BitstringStatusList,
124
127
  [
125
- "lds"
128
+ "lds",
129
+ "vc+jwt"
126
130
  ]
127
131
  ]
128
132
  ]);
@@ -137,29 +141,50 @@ function determineStatusListType(credential) {
137
141
  const proofFormat = determineProofFormat(credential);
138
142
  switch (proofFormat) {
139
143
  case "jwt":
140
- const payload = (0, import_jwt_decode.jwtDecode)(credential);
141
- const keys = Object.keys(payload);
142
- if (keys.includes("status_list")) {
143
- return import_ssi_types.StatusListType.OAuthStatusList;
144
- } else if (keys.includes("vc")) {
145
- return import_ssi_types.StatusListType.StatusList2021;
146
- }
147
- break;
144
+ return determineJwtStatusListType(credential);
148
145
  case "lds":
149
- const uniform = import_ssi_types.CredentialMapper.toUniformCredential(credential);
150
- const type = uniform.type.find((t) => {
151
- return Object.values(import_ssi_types.StatusListType).some((statusType) => t.includes(statusType));
152
- });
153
- if (!type) {
154
- throw new Error("Invalid status list credential type");
155
- }
156
- return type.replace("Credential", "");
146
+ return determineLdsStatusListType(credential);
157
147
  case "cbor":
158
148
  return import_ssi_types.StatusListType.OAuthStatusList;
149
+ default:
150
+ throw new Error("Cannot determine status list type from credential payload");
159
151
  }
160
- throw new Error("Cannot determine status list type from credential payload");
161
152
  }
162
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");
163
188
  function determineProofFormat(credential) {
164
189
  const type = import_ssi_types.CredentialMapper.detectDocumentType(credential);
165
190
  switch (type) {
@@ -174,6 +199,26 @@ function determineProofFormat(credential) {
174
199
  }
175
200
  }
176
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");
177
222
 
178
223
  // src/impl/StatusList2021.ts
179
224
  var import_ssi_types2 = require("@sphereon/ssi-types");
@@ -237,13 +282,14 @@ var StatusList2021Implementation = class {
237
282
  encodedList,
238
283
  proofFormat
239
284
  }, context);
285
+ if (!("statusPurpose" in credentialSubject)) {
286
+ return Promise.reject(Error("statusPurpose is required in credentialSubject for StatusList2021"));
287
+ }
240
288
  return {
241
289
  statusListCredential: updatedCredential,
242
290
  encodedList,
243
291
  statusList2021: {
244
- ..."statusPurpose" in credentialSubject ? {
245
- statusPurpose: credentialSubject.statusPurpose
246
- } : {},
292
+ statusPurpose: credentialSubject.statusPurpose,
247
293
  indexingDirection: "rightToLeft"
248
294
  },
249
295
  length: statusList.length - 1,
@@ -300,36 +346,88 @@ var StatusList2021Implementation = class {
300
346
  const status = statusList.getStatus(typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex));
301
347
  return status ? Status2021.Invalid : Status2021.Valid;
302
348
  }
303
- async toStatusListDetails(args) {
304
- const { statusListPayload } = args;
305
- const uniform = import_ssi_types2.CredentialMapper.toUniformCredential(statusListPayload);
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);
306
356
  const { issuer, credentialSubject } = uniform;
307
- const id = getAssertedValue("id", uniform.id);
308
- const encodedList = getAssertedProperty("encodedList", credentialSubject);
309
- const proofFormat = import_ssi_types2.CredentialMapper.detectDocumentType(statusListPayload) === import_ssi_types2.DocumentFormat.JWT ? "jwt" : "lds";
310
- const statusPurpose = getAssertedProperty("statusPurpose", credentialSubject);
311
- const list = await import_vc_status_list.StatusList.decode({
312
- encodedList
313
- });
357
+ const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
314
358
  return {
315
- id,
316
- encodedList,
359
+ id: getAssertedValue("id", uniform.id),
317
360
  issuer,
318
- type: import_ssi_types2.StatusListType.StatusList2021,
319
- proofFormat,
320
- length: list.length,
321
- statusListCredential: statusListPayload,
322
- statuslistContentType: this.buildContentType(proofFormat),
323
- statusList2021: {
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,
324
388
  indexingDirection: "rightToLeft",
325
- statusPurpose
326
- },
327
- ...args.correlationId && {
328
- correlationId: args.correlationId
329
- },
330
- ...args.driverType && {
331
- driverType: args.driverType
332
- }
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
333
431
  };
334
432
  }
335
433
  async createVerifiableCredential(args, context) {
@@ -624,7 +722,8 @@ var OAuthStatusListImplementation = class {
624
722
  }
625
723
  const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT2;
626
724
  const { issuer, id, oauthStatusList, keyRef } = args;
627
- const { bitsPerStatus, expiresAt } = oauthStatusList;
725
+ const { bitsPerStatus } = oauthStatusList;
726
+ const expiresAt = ensureDate(oauthStatusList.expiresAt);
628
727
  const length = args.length ?? DEFAULT_LIST_LENGTH2;
629
728
  const issuerString = typeof issuer === "string" ? issuer : issuer.id;
630
729
  const correlationId = getAssertedValue("correlationId", args.correlationId);
@@ -647,7 +746,8 @@ var OAuthStatusListImplementation = class {
647
746
  };
648
747
  }
649
748
  async updateStatusListIndex(args, context) {
650
- const { statusListCredential, value, expiresAt, keyRef } = args;
749
+ const { statusListCredential, value, keyRef } = args;
750
+ const expiresAt = ensureDate(args.expiresAt);
651
751
  if (typeof statusListCredential !== "string") {
652
752
  return Promise.reject("statusListCredential in neither JWT nor CWT");
653
753
  }
@@ -683,7 +783,8 @@ var OAuthStatusListImplementation = class {
683
783
  throw new Error("OAuthStatusList options are required for type OAuthStatusList");
684
784
  }
685
785
  const { proofFormat, oauthStatusList, keyRef } = args;
686
- const { bitsPerStatus, expiresAt } = oauthStatusList;
786
+ const { bitsPerStatus } = oauthStatusList;
787
+ const expiresAt = ensureDate(oauthStatusList.expiresAt);
687
788
  const { issuer, id } = getAssertedValues(args);
688
789
  const issuerString = typeof issuer === "string" ? issuer : issuer.id;
689
790
  const listToUpdate = import_jwt_status_list3.StatusList.decompressStatusList(args.encodedList, bitsPerStatus ?? DEFAULT_BITS_PER_STATUS);
@@ -705,9 +806,6 @@ var OAuthStatusListImplementation = class {
705
806
  statuslistContentType: this.buildContentType(proofFormat)
706
807
  };
707
808
  }
708
- buildContentType(proofFormat) {
709
- return `application/statuslist+${proofFormat === "cbor" ? "cwt" : "jwt"}`;
710
- }
711
809
  async checkStatusIndex(args) {
712
810
  const { statusListCredential, statusListIndex } = args;
713
811
  if (typeof statusListCredential !== "string") {
@@ -721,34 +819,101 @@ var OAuthStatusListImplementation = class {
721
819
  }
722
820
  return statusList.getStatus(index);
723
821
  }
724
- async toStatusListDetails(args) {
725
- const { statusListPayload } = args;
726
- const proofFormat = determineProofFormat(statusListPayload);
727
- const decoded = proofFormat === "jwt" ? decodeStatusListJWT(statusListPayload) : decodeStatusListCWT(statusListPayload);
728
- const { statusList, issuer, id, exp } = decoded;
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);
729
833
  return {
730
- id,
731
- encodedList: statusList.compressStatusList(),
732
- issuer,
733
- type: import_ssi_types4.StatusListType.OAuthStatusList,
734
- proofFormat,
735
- length: statusList.statusList.length,
736
- statusListCredential: statusListPayload,
737
- statuslistContentType: this.buildContentType(proofFormat),
738
- oauthStatusList: {
739
- bitsPerStatus: statusList.getBitsPerStatus(),
740
- ...exp && {
741
- expiresAt: new Date(exp * 1e3)
742
- }
743
- },
744
- ...args.correlationId && {
745
- correlationId: args.correlationId
746
- },
747
- ...args.driverType && {
748
- 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"));
749
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
750
912
  };
751
913
  }
914
+ buildContentType(proofFormat) {
915
+ return `application/statuslist+${proofFormat === "cbor" ? "cwt" : "jwt"}`;
916
+ }
752
917
  async createSignedStatusList(proofFormat, context, statusList, issuerString, id, expiresAt, keyRef) {
753
918
  switch (proofFormat) {
754
919
  case "jwt": {
@@ -770,12 +935,19 @@ var import_ssi_types6 = require("@sphereon/ssi-types");
770
935
  var import_ssi_types5 = require("@sphereon/ssi-types");
771
936
  var import_vc_bitstring_status_lists = require("@4sure-tech/vc-bitstring-status-lists");
772
937
  var DEFAULT_LIST_LENGTH3 = 131072;
773
- var DEFAULT_PROOF_FORMAT3 = "lds";
938
+ var DEFAULT_PROOF_FORMAT3 = "vc+jwt";
774
939
  var DEFAULT_STATUS_PURPOSE = "revocation";
775
940
  var BitstringStatusListImplementation = class {
776
941
  static {
777
942
  __name(this, "BitstringStatusListImplementation");
778
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
+ */
779
951
  async createNewStatusList(args, context) {
780
952
  if (!args.bitstringStatusList) {
781
953
  throw new Error("BitstringStatusList options are required for type BitstringStatusList");
@@ -783,28 +955,34 @@ var BitstringStatusListImplementation = class {
783
955
  const length = args?.length ?? DEFAULT_LIST_LENGTH3;
784
956
  const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT3;
785
957
  assertValidProofType(import_ssi_types5.StatusListType.BitstringStatusList, proofFormat);
786
- const veramoProofFormat = proofFormat;
787
958
  const { issuer, id } = args;
788
959
  const correlationId = getAssertedValue("correlationId", args.correlationId);
789
960
  const { statusPurpose, bitsPerStatus, validFrom, validUntil, ttl } = args.bitstringStatusList;
790
- const statusListCredential = await this.createVerifiableCredential({
791
- ...args,
792
- proofFormat: veramoProofFormat,
961
+ const unsignedCredential = await (0, import_vc_bitstring_status_lists.createStatusListCredential)({
962
+ id,
963
+ issuer,
793
964
  statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
794
- validFrom,
795
- validUntil,
965
+ validFrom: ensureDate(validFrom),
966
+ validUntil: ensureDate(validUntil),
796
967
  ttl
968
+ });
969
+ const statusListCredential = await this.createVerifiableCredential({
970
+ unsignedCredential,
971
+ id,
972
+ issuer,
973
+ proofFormat,
974
+ keyRef: args.keyRef
797
975
  }, context);
798
976
  return {
799
- encodedList: statusListCredential.credentialSubject.encodedList,
977
+ encodedList: unsignedCredential.credentialSubject.encodedList,
800
978
  statusListCredential,
801
979
  bitstringStatusList: {
802
980
  statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
803
- ...statusListCredential.validFrom && {
804
- validFrom: new Date(statusListCredential.validFrom)
981
+ ...unsignedCredential.validFrom && {
982
+ validFrom: new Date(unsignedCredential.validFrom)
805
983
  },
806
- ...statusListCredential.validUntil && {
807
- validUntil: new Date(statusListCredential.validUntil)
984
+ ...unsignedCredential.validUntil && {
985
+ validUntil: new Date(unsignedCredential.validUntil)
808
986
  },
809
987
  ttl,
810
988
  bitsPerStatus
@@ -818,9 +996,16 @@ var BitstringStatusListImplementation = class {
818
996
  statuslistContentType: this.buildContentType(proofFormat)
819
997
  };
820
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
+ */
821
1006
  async updateStatusListIndex(args, context) {
822
1007
  if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
823
- return Promise.reject("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListIndex)");
1008
+ return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListIndex)"));
824
1009
  }
825
1010
  const credential = args.statusListCredential;
826
1011
  const uniform = import_ssi_types5.CredentialMapper.toUniformCredential(credential);
@@ -832,34 +1017,40 @@ var BitstringStatusListImplementation = class {
832
1017
  encodedList: origEncodedList,
833
1018
  statusSize: args.bitsPerStatus
834
1019
  });
835
- statusList.setStatus(index, args.value);
836
- 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";
837
1023
  const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
838
1024
  const statusPurpose = getAssertedProperty("statusPurpose", credSubject);
839
1025
  const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : void 0;
840
1026
  const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : void 0;
841
1027
  const ttl = credSubject.ttl;
842
- const updatedCredential = await this.createVerifiableCredential({
843
- ...args,
1028
+ const unsignedCredential = await (0, import_vc_bitstring_status_lists.createStatusListCredential)({
844
1029
  id,
845
1030
  issuer,
846
1031
  statusList,
1032
+ statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
1033
+ validFrom: ensureDate(validFrom),
1034
+ validUntil: ensureDate(validUntil),
1035
+ ttl
1036
+ });
1037
+ const updatedCredential = await this.createVerifiableCredential({
1038
+ unsignedCredential,
1039
+ id,
1040
+ issuer,
847
1041
  proofFormat,
848
- statusPurpose,
849
- ttl,
850
- validFrom,
851
- validUntil
1042
+ keyRef: args.keyRef
852
1043
  }, context);
853
1044
  return {
854
1045
  statusListCredential: updatedCredential,
855
- encodedList: updatedCredential.credentialSubject.encodedList,
1046
+ encodedList: unsignedCredential.credentialSubject.encodedList,
856
1047
  bitstringStatusList: {
857
1048
  statusPurpose,
858
- ...updatedCredential.validFrom && {
859
- validFrom: new Date(updatedCredential.validFrom)
1049
+ ...unsignedCredential.validFrom && {
1050
+ validFrom: new Date(unsignedCredential.validFrom)
860
1051
  },
861
- ...updatedCredential.validUntil && {
862
- validUntil: new Date(updatedCredential.validUntil)
1052
+ ...unsignedCredential.validUntil && {
1053
+ validUntil: new Date(unsignedCredential.validUntil)
863
1054
  },
864
1055
  bitsPerStatus: args.bitsPerStatus,
865
1056
  ttl
@@ -872,17 +1063,23 @@ var BitstringStatusListImplementation = class {
872
1063
  statuslistContentType: this.buildContentType(proofFormat)
873
1064
  };
874
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
+ */
875
1073
  async updateStatusListFromEncodedList(args, context) {
876
1074
  if (!args.bitstringStatusList) {
877
1075
  throw new Error("bitstringStatusList options required for type BitstringStatusList");
878
1076
  }
879
1077
  if (args.bitstringStatusList.bitsPerStatus < 1) {
880
- return Promise.reject("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListFromEncodedList)");
1078
+ return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListFromEncodedList)"));
881
1079
  }
882
1080
  const { statusPurpose, bitsPerStatus, ttl, validFrom, validUntil } = args.bitstringStatusList;
883
1081
  const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT3;
884
1082
  assertValidProofType(import_ssi_types5.StatusListType.BitstringStatusList, proofFormat);
885
- const veramoProofFormat = proofFormat;
886
1083
  const { issuer, id } = getAssertedValues(args);
887
1084
  const statusList = await import_vc_bitstring_status_lists.BitstreamStatusList.decode({
888
1085
  encodedList: args.encodedList,
@@ -890,29 +1087,34 @@ var BitstringStatusListImplementation = class {
890
1087
  });
891
1088
  const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
892
1089
  statusList.setStatus(index, args.value);
893
- const credential = await this.createVerifiableCredential({
1090
+ const unsignedCredential = await (0, import_vc_bitstring_status_lists.createStatusListCredential)({
894
1091
  id,
895
1092
  issuer,
896
1093
  statusList,
897
- proofFormat: veramoProofFormat,
898
- keyRef: args.keyRef,
899
- statusPurpose,
900
- validFrom,
901
- validUntil,
1094
+ statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
1095
+ validFrom: ensureDate(validFrom),
1096
+ validUntil: ensureDate(validUntil),
902
1097
  ttl
1098
+ });
1099
+ const credential = await this.createVerifiableCredential({
1100
+ unsignedCredential,
1101
+ id,
1102
+ issuer,
1103
+ proofFormat,
1104
+ keyRef: args.keyRef
903
1105
  }, context);
904
1106
  return {
905
1107
  type: import_ssi_types5.StatusListType.BitstringStatusList,
906
1108
  statusListCredential: credential,
907
- encodedList: credential.credentialSubject.encodedList,
1109
+ encodedList: unsignedCredential.credentialSubject.encodedList,
908
1110
  bitstringStatusList: {
909
1111
  statusPurpose,
910
1112
  bitsPerStatus,
911
- ...credential.validFrom && {
912
- validFrom: new Date(credential.validFrom)
1113
+ ...unsignedCredential.validFrom && {
1114
+ validFrom: new Date(unsignedCredential.validFrom)
913
1115
  },
914
- ...credential.validUntil && {
915
- validUntil: new Date(credential.validUntil)
1116
+ ...unsignedCredential.validUntil && {
1117
+ validUntil: new Date(unsignedCredential.validUntil)
916
1118
  },
917
1119
  ttl
918
1120
  },
@@ -923,17 +1125,22 @@ var BitstringStatusListImplementation = class {
923
1125
  statuslistContentType: this.buildContentType(proofFormat)
924
1126
  };
925
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
+ */
926
1134
  async checkStatusIndex(args) {
927
1135
  if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
928
- return Promise.reject("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (checkStatusIndex)");
1136
+ return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (checkStatusIndex)"));
929
1137
  }
930
1138
  const uniform = import_ssi_types5.CredentialMapper.toUniformCredential(args.statusListCredential);
931
1139
  const { credentialSubject } = uniform;
932
1140
  const encodedList = getAssertedProperty("encodedList", credentialSubject);
933
- const statusSize = args.bitsPerStatus;
934
1141
  const statusList = await import_vc_bitstring_status_lists.BitstreamStatusList.decode({
935
1142
  encodedList,
936
- statusSize
1143
+ statusSize: args.bitsPerStatus
937
1144
  });
938
1145
  const numIndex = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
939
1146
  if (statusList.getLength() <= numIndex) {
@@ -941,67 +1148,177 @@ var BitstringStatusListImplementation = class {
941
1148
  }
942
1149
  return statusList.getStatus(numIndex);
943
1150
  }
944
- async toStatusListDetails(args) {
945
- const { statusListPayload, bitsPerStatus } = args;
946
- if (!bitsPerStatus || bitsPerStatus < 1) {
947
- return Promise.reject("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (toStatusListDetails)");
948
- }
949
- const uniform = import_ssi_types5.CredentialMapper.toUniformCredential(statusListPayload);
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);
950
1158
  const { issuer, credentialSubject } = uniform;
951
- const id = getAssertedValue("id", uniform.id);
952
- const encodedList = getAssertedProperty("encodedList", credentialSubject);
953
- const proofFormat = import_ssi_types5.CredentialMapper.detectDocumentType(statusListPayload) === import_ssi_types5.DocumentFormat.JWT ? "jwt" : "lds";
954
- const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
955
- const statusPurpose = getAssertedProperty("statusPurpose", credSubject);
956
- const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : void 0;
957
- const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : void 0;
958
- const ttl = credSubject.ttl;
959
- const statuslistLength = import_vc_bitstring_status_lists.BitstreamStatusList.getStatusListLength(encodedList, bitsPerStatus);
1159
+ const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
960
1160
  return {
961
- id,
962
- encodedList,
1161
+ id: getAssertedValue("id", uniform.id),
963
1162
  issuer,
964
- type: import_ssi_types5.StatusListType.BitstringStatusList,
965
- proofFormat,
966
- length: statuslistLength,
967
- statusListCredential: statusListPayload,
968
- statuslistContentType: this.buildContentType(proofFormat),
969
- bitstringStatusList: {
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,
970
1194
  statusPurpose,
971
1195
  bitsPerStatus,
972
- validFrom,
973
- validUntil,
974
- ttl
975
- },
976
- ...args.correlationId && {
977
- correlationId: args.correlationId
978
- },
979
- ...args.driverType && {
980
- driverType: args.driverType
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"));
981
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
982
1284
  };
983
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
+ */
984
1293
  async createVerifiableCredential(args, context) {
1294
+ const { unsignedCredential, issuer, proofFormat, keyRef } = args;
985
1295
  const identifier = await context.agent.identifierManagedGet({
986
- identifier: typeof args.issuer === "string" ? args.issuer : args.issuer.id,
1296
+ identifier: typeof issuer === "string" ? issuer : issuer.id,
987
1297
  vmRelationship: "assertionMethod",
988
1298
  offlineWhenNoDIDRegistered: true
989
1299
  });
990
- const unsignedCredential = await (0, import_vc_bitstring_status_lists.createStatusListCredential)(args);
991
1300
  const verifiableCredential = await context.agent.createVerifiableCredential({
992
1301
  credential: unsignedCredential,
993
- keyRef: args.keyRef ?? identifier.kmsKeyRef,
994
- proofFormat: args.proofFormat,
1302
+ keyRef: keyRef ?? identifier.kmsKeyRef,
1303
+ proofFormat,
995
1304
  fetchRemoteContexts: true
996
1305
  });
997
1306
  return import_ssi_types5.CredentialMapper.toWrappedVerifiableCredential(verifiableCredential).original;
998
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
+ */
999
1314
  buildContentType(proofFormat) {
1000
1315
  switch (proofFormat) {
1001
1316
  case "jwt":
1002
- return `application/statuslist+jwt`;
1317
+ return "application/statuslist+jwt";
1003
1318
  case "cbor":
1004
- return `application/statuslist+cwt`;
1319
+ return "application/statuslist+cwt";
1320
+ case "vc+jwt":
1321
+ return "application/statuslist+vc+jwt";
1005
1322
  case "lds":
1006
1323
  return "application/statuslist+ld+json";
1007
1324
  default:
@@ -1157,36 +1474,35 @@ async function updateStatusIndexFromStatusListCredential(args, context) {
1157
1474
  return implementation.updateStatusListIndex(args, context);
1158
1475
  }
1159
1476
  __name(updateStatusIndexFromStatusListCredential, "updateStatusIndexFromStatusListCredential");
1160
- async function statusListCredentialToDetails({ correlationId, driverType, statusListCredential, bitsPerStatus }) {
1161
- const credential = getAssertedValue("statusListCredential", statusListCredential);
1162
- let statusListType;
1163
- const documentFormat = import_ssi_types7.CredentialMapper.detectDocumentType(credential);
1164
- if (documentFormat === import_ssi_types7.DocumentFormat.JWT) {
1165
- const [header] = credential.split(".");
1166
- const decodedHeader = JSON.parse(Buffer.from(header, "base64").toString());
1167
- if (decodedHeader.typ === "statuslist+jwt") {
1168
- statusListType = import_ssi_types7.StatusListType.OAuthStatusList;
1169
- }
1170
- } else if (documentFormat === import_ssi_types7.DocumentFormat.MSO_MDOC) {
1171
- statusListType = import_ssi_types7.StatusListType.OAuthStatusList;
1172
- }
1173
- if (!statusListType) {
1174
- const uniform = import_ssi_types7.CredentialMapper.toUniformCredential(credential);
1175
- const type = uniform.type.find((t) => t.includes("StatusList2021") || t.includes("OAuth2StatusList") || t.includes("BitstringStatusList"));
1176
- if (!type) {
1177
- throw new Error("Invalid status list credential type");
1178
- }
1179
- 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);
1180
1492
  }
1493
+ }
1494
+ __name(toStatusListDetails, "toStatusListDetails");
1495
+ async function createCredentialStatusFromStatusList(args) {
1496
+ const { statusList, statusListEntry, statusListIndex } = args;
1497
+ const statusListType = determineStatusListType(statusList.statusListCredential);
1181
1498
  const implementation = getStatusListImplementation(statusListType);
1182
- return await implementation.toStatusListDetails({
1183
- statusListPayload: credential,
1184
- correlationId,
1185
- driverType,
1186
- bitsPerStatus
1499
+ return implementation.createCredentialStatus({
1500
+ statusList,
1501
+ statusListEntry,
1502
+ statusListIndex
1187
1503
  });
1188
1504
  }
1189
- __name(statusListCredentialToDetails, "statusListCredentialToDetails");
1505
+ __name(createCredentialStatusFromStatusList, "createCredentialStatusFromStatusList");
1190
1506
  async function updateStatusListIndexFromEncodedList(args, context) {
1191
1507
  const { type } = getAssertedValue("type", args);
1192
1508
  const implementation = getStatusListImplementation(type);