@sphereon/ssi-sdk.vc-status-list 0.34.1-feature.SSISDK.17.bitstring.sl.9 → 0.34.1-next.29

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.js CHANGED
@@ -15,7 +15,7 @@ var Status2021 = /* @__PURE__ */ function(Status20212) {
15
15
  }({});
16
16
 
17
17
  // src/functions.ts
18
- import { CredentialMapper as CredentialMapper4, DocumentFormat as DocumentFormat4, StatusListType as StatusListType6 } from "@sphereon/ssi-types";
18
+ import { CredentialMapper as CredentialMapper4, StatusListType as StatusListType6 } from "@sphereon/ssi-types";
19
19
  import { checkStatus } from "@sphereon/vc-status-list";
20
20
 
21
21
  // src/utils.ts
@@ -76,7 +76,8 @@ var ValidProofTypeMap = /* @__PURE__ */ new Map([
76
76
  [
77
77
  StatusListType.BitstringStatusList,
78
78
  [
79
- "lds"
79
+ "lds",
80
+ "vc+jwt"
80
81
  ]
81
82
  ]
82
83
  ]);
@@ -91,29 +92,50 @@ function determineStatusListType(credential) {
91
92
  const proofFormat = determineProofFormat(credential);
92
93
  switch (proofFormat) {
93
94
  case "jwt":
94
- const payload = jwtDecode(credential);
95
- const keys = Object.keys(payload);
96
- if (keys.includes("status_list")) {
97
- return StatusListType.OAuthStatusList;
98
- } else if (keys.includes("vc")) {
99
- return StatusListType.StatusList2021;
100
- }
101
- break;
95
+ return determineJwtStatusListType(credential);
102
96
  case "lds":
103
- const uniform = CredentialMapper.toUniformCredential(credential);
104
- const type = uniform.type.find((t) => {
105
- return Object.values(StatusListType).some((statusType) => t.includes(statusType));
106
- });
107
- if (!type) {
108
- throw new Error("Invalid status list credential type");
109
- }
110
- return type.replace("Credential", "");
97
+ return determineLdsStatusListType(credential);
111
98
  case "cbor":
112
99
  return StatusListType.OAuthStatusList;
100
+ default:
101
+ throw new Error("Cannot determine status list type from credential payload");
113
102
  }
114
- throw new Error("Cannot determine status list type from credential payload");
115
103
  }
116
104
  __name(determineStatusListType, "determineStatusListType");
105
+ function determineJwtStatusListType(credential) {
106
+ const payload = jwtDecode(credential);
107
+ if ("status_list" in payload) {
108
+ return StatusListType.OAuthStatusList;
109
+ }
110
+ if ("credentialSubject" in payload) {
111
+ return getStatusListTypeFromSubject(payload.credentialSubject);
112
+ }
113
+ if ("vc" in payload && "credentialSubject" in payload.vc) {
114
+ return getStatusListTypeFromSubject(payload.vc.credentialSubject);
115
+ }
116
+ throw new Error("Invalid status list credential: credentialSubject not found");
117
+ }
118
+ __name(determineJwtStatusListType, "determineJwtStatusListType");
119
+ function determineLdsStatusListType(credential) {
120
+ const uniform = CredentialMapper.toUniformCredential(credential);
121
+ const statusListType = uniform.type.find((type) => Object.values(StatusListType).some((statusType) => type.includes(statusType)));
122
+ if (!statusListType) {
123
+ throw new Error("Invalid status list credential type");
124
+ }
125
+ return statusListType.replace("Credential", "");
126
+ }
127
+ __name(determineLdsStatusListType, "determineLdsStatusListType");
128
+ function getStatusListTypeFromSubject(credentialSubject) {
129
+ switch (credentialSubject.type) {
130
+ case "StatusList2021":
131
+ return StatusListType.StatusList2021;
132
+ case "BitstringStatusList":
133
+ return StatusListType.BitstringStatusList;
134
+ default:
135
+ throw new Error(`Unknown credential subject type: ${credentialSubject.type}`);
136
+ }
137
+ }
138
+ __name(getStatusListTypeFromSubject, "getStatusListTypeFromSubject");
117
139
  function determineProofFormat(credential) {
118
140
  const type = CredentialMapper.detectDocumentType(credential);
119
141
  switch (type) {
@@ -211,13 +233,14 @@ var StatusList2021Implementation = class {
211
233
  encodedList,
212
234
  proofFormat
213
235
  }, context);
236
+ if (!("statusPurpose" in credentialSubject)) {
237
+ return Promise.reject(Error("statusPurpose is required in credentialSubject for StatusList2021"));
238
+ }
214
239
  return {
215
240
  statusListCredential: updatedCredential,
216
241
  encodedList,
217
242
  statusList2021: {
218
- ..."statusPurpose" in credentialSubject ? {
219
- statusPurpose: credentialSubject.statusPurpose
220
- } : {},
243
+ statusPurpose: credentialSubject.statusPurpose,
221
244
  indexingDirection: "rightToLeft"
222
245
  },
223
246
  length: statusList.length - 1,
@@ -274,36 +297,88 @@ var StatusList2021Implementation = class {
274
297
  const status = statusList.getStatus(typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex));
275
298
  return status ? Status2021.Invalid : Status2021.Valid;
276
299
  }
277
- async toStatusListDetails(args) {
278
- const { statusListPayload } = args;
279
- const uniform = CredentialMapper2.toUniformCredential(statusListPayload);
300
+ /**
301
+ * Performs the initial parsing of a StatusListCredential.
302
+ * This method handles expensive operations like JWT/CWT decoding once.
303
+ * It extracts all details available from the credential payload itself.
304
+ */
305
+ async extractCredentialDetails(credential) {
306
+ const uniform = CredentialMapper2.toUniformCredential(credential);
280
307
  const { issuer, credentialSubject } = uniform;
281
- const id = getAssertedValue("id", uniform.id);
282
- const encodedList = getAssertedProperty("encodedList", credentialSubject);
283
- const proofFormat = CredentialMapper2.detectDocumentType(statusListPayload) === DocumentFormat2.JWT ? "jwt" : "lds";
284
- const statusPurpose = getAssertedProperty("statusPurpose", credentialSubject);
285
- const list = await StatusList.decode({
286
- encodedList
287
- });
308
+ const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
288
309
  return {
289
- id,
290
- encodedList,
310
+ id: getAssertedValue("id", uniform.id),
291
311
  issuer,
292
- type: StatusListType2.StatusList2021,
293
- proofFormat,
294
- length: list.length,
295
- statusListCredential: statusListPayload,
296
- statuslistContentType: this.buildContentType(proofFormat),
297
- statusList2021: {
312
+ encodedList: getAssertedProperty("encodedList", subject)
313
+ };
314
+ }
315
+ async toStatusListDetails(args) {
316
+ if ("statusListCredential" in args) {
317
+ const { statusListCredential, correlationId, driverType } = args;
318
+ const uniform = CredentialMapper2.toUniformCredential(statusListCredential);
319
+ const { issuer, credentialSubject } = uniform;
320
+ const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
321
+ const id = getAssertedValue("id", uniform.id);
322
+ const encodedList = getAssertedProperty("encodedList", subject);
323
+ const statusPurpose = getAssertedProperty("statusPurpose", subject);
324
+ const proofFormat = CredentialMapper2.detectDocumentType(statusListCredential) === DocumentFormat2.JWT ? "jwt" : "lds";
325
+ const list = await StatusList.decode({
326
+ encodedList
327
+ });
328
+ return {
329
+ id,
330
+ encodedList,
331
+ issuer,
332
+ type: StatusListType2.StatusList2021,
333
+ proofFormat,
334
+ length: list.length,
335
+ statusListCredential,
336
+ statuslistContentType: this.buildContentType(proofFormat),
337
+ correlationId,
338
+ driverType,
298
339
  indexingDirection: "rightToLeft",
299
- statusPurpose
300
- },
301
- ...args.correlationId && {
302
- correlationId: args.correlationId
303
- },
304
- ...args.driverType && {
305
- driverType: args.driverType
306
- }
340
+ statusPurpose,
341
+ statusList2021: {
342
+ indexingDirection: "rightToLeft",
343
+ statusPurpose
344
+ }
345
+ };
346
+ } else {
347
+ const { extractedDetails, statusListEntity } = args;
348
+ const statusList2021Entity = statusListEntity;
349
+ const proofFormat = CredentialMapper2.detectDocumentType(statusListEntity.statusListCredential) === DocumentFormat2.JWT ? "jwt" : "lds";
350
+ const list = await StatusList.decode({
351
+ encodedList: extractedDetails.encodedList
352
+ });
353
+ return {
354
+ id: extractedDetails.id,
355
+ encodedList: extractedDetails.encodedList,
356
+ issuer: extractedDetails.issuer,
357
+ type: StatusListType2.StatusList2021,
358
+ proofFormat,
359
+ length: list.length,
360
+ statusListCredential: statusListEntity.statusListCredential,
361
+ statuslistContentType: this.buildContentType(proofFormat),
362
+ correlationId: statusListEntity.correlationId,
363
+ driverType: statusListEntity.driverType,
364
+ indexingDirection: statusList2021Entity.indexingDirection,
365
+ statusPurpose: statusList2021Entity.statusPurpose,
366
+ statusList2021: {
367
+ indexingDirection: statusList2021Entity.indexingDirection,
368
+ statusPurpose: statusList2021Entity.statusPurpose
369
+ }
370
+ };
371
+ }
372
+ }
373
+ async createCredentialStatus(args) {
374
+ const { statusList, statusListIndex } = args;
375
+ const statusList2021 = statusList;
376
+ return {
377
+ id: `${statusList.id}#${statusListIndex}`,
378
+ type: "StatusList2021Entry",
379
+ statusPurpose: statusList2021.statusPurpose ?? "revocation",
380
+ statusListIndex: "" + statusListIndex,
381
+ statusListCredential: statusList.id
307
382
  };
308
383
  }
309
384
  async createVerifiableCredential(args, context) {
@@ -597,9 +672,9 @@ var OAuthStatusListImplementation = class {
597
672
  throw new Error("OAuthStatusList options are required for type OAuthStatusList");
598
673
  }
599
674
  const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT2;
600
- const { issuer, id, oauthStatusList: oauthStatusList1, keyRef } = args;
601
- const { bitsPerStatus } = oauthStatusList1;
602
- const expiresAt = ensureDate(oauthStatusList1.expiresAt);
675
+ const { issuer, id, oauthStatusList, keyRef } = args;
676
+ const { bitsPerStatus } = oauthStatusList;
677
+ const expiresAt = ensureDate(oauthStatusList.expiresAt);
603
678
  const length = args.length ?? DEFAULT_LIST_LENGTH2;
604
679
  const issuerString = typeof issuer === "string" ? issuer : issuer.id;
605
680
  const correlationId = getAssertedValue("correlationId", args.correlationId);
@@ -623,7 +698,7 @@ var OAuthStatusListImplementation = class {
623
698
  }
624
699
  async updateStatusListIndex(args, context) {
625
700
  const { statusListCredential, value, keyRef } = args;
626
- const expiresAt = ensureDate(oauthStatusList.expiresAt);
701
+ const expiresAt = ensureDate(args.expiresAt);
627
702
  if (typeof statusListCredential !== "string") {
628
703
  return Promise.reject("statusListCredential in neither JWT nor CWT");
629
704
  }
@@ -658,9 +733,9 @@ var OAuthStatusListImplementation = class {
658
733
  if (!args.oauthStatusList) {
659
734
  throw new Error("OAuthStatusList options are required for type OAuthStatusList");
660
735
  }
661
- const { proofFormat, oauthStatusList: oauthStatusList1, keyRef } = args;
662
- const { bitsPerStatus } = oauthStatusList1;
663
- const expiresAt = ensureDate(oauthStatusList1.expiresAt);
736
+ const { proofFormat, oauthStatusList, keyRef } = args;
737
+ const { bitsPerStatus } = oauthStatusList;
738
+ const expiresAt = ensureDate(oauthStatusList.expiresAt);
664
739
  const { issuer, id } = getAssertedValues(args);
665
740
  const issuerString = typeof issuer === "string" ? issuer : issuer.id;
666
741
  const listToUpdate = StatusList4.decompressStatusList(args.encodedList, bitsPerStatus ?? DEFAULT_BITS_PER_STATUS);
@@ -682,9 +757,6 @@ var OAuthStatusListImplementation = class {
682
757
  statuslistContentType: this.buildContentType(proofFormat)
683
758
  };
684
759
  }
685
- buildContentType(proofFormat) {
686
- return `application/statuslist+${proofFormat === "cbor" ? "cwt" : "jwt"}`;
687
- }
688
760
  async checkStatusIndex(args) {
689
761
  const { statusListCredential, statusListIndex } = args;
690
762
  if (typeof statusListCredential !== "string") {
@@ -698,34 +770,101 @@ var OAuthStatusListImplementation = class {
698
770
  }
699
771
  return statusList.getStatus(index);
700
772
  }
701
- async toStatusListDetails(args) {
702
- const { statusListPayload } = args;
703
- const proofFormat = determineProofFormat(statusListPayload);
704
- const decoded = proofFormat === "jwt" ? decodeStatusListJWT(statusListPayload) : decodeStatusListCWT(statusListPayload);
705
- const { statusList, issuer, id, exp } = decoded;
773
+ /**
774
+ * Performs the initial parsing of a StatusListCredential.
775
+ * This method handles expensive operations like JWT/CWT decoding once.
776
+ * It extracts all details available from the credential payload itself.
777
+ */
778
+ async extractCredentialDetails(credential) {
779
+ if (typeof credential !== "string") {
780
+ return Promise.reject("statusListCredential must be a JWT or CWT string");
781
+ }
782
+ const proofFormat = determineProofFormat(credential);
783
+ const decoded = proofFormat === "jwt" ? decodeStatusListJWT(credential) : decodeStatusListCWT(credential);
706
784
  return {
707
- id,
708
- encodedList: statusList.compressStatusList(),
709
- issuer,
710
- type: StatusListType3.OAuthStatusList,
711
- proofFormat,
712
- length: statusList.statusList.length,
713
- statusListCredential: statusListPayload,
714
- statuslistContentType: this.buildContentType(proofFormat),
715
- oauthStatusList: {
716
- bitsPerStatus: statusList.getBitsPerStatus(),
717
- ...exp && {
718
- expiresAt: new Date(exp * 1e3)
719
- }
720
- },
721
- ...args.correlationId && {
722
- correlationId: args.correlationId
723
- },
724
- ...args.driverType && {
725
- driverType: args.driverType
785
+ id: decoded.id,
786
+ issuer: decoded.issuer,
787
+ encodedList: decoded.statusList.compressStatusList(),
788
+ decodedPayload: decoded
789
+ };
790
+ }
791
+ async toStatusListDetails(args) {
792
+ if ("statusListCredential" in args) {
793
+ const { statusListCredential, bitsPerStatus, correlationId, driverType } = args;
794
+ if (!bitsPerStatus || bitsPerStatus < 1) {
795
+ return Promise.reject(Error("bitsPerStatus must be set for OAuth status lists and must be 1 or higher"));
726
796
  }
797
+ const proofFormat = determineProofFormat(statusListCredential);
798
+ const decoded = proofFormat === "jwt" ? decodeStatusListJWT(statusListCredential) : decodeStatusListCWT(statusListCredential);
799
+ const { statusList, issuer, id, exp } = decoded;
800
+ const expiresAt = exp ? new Date(exp * 1e3) : void 0;
801
+ return {
802
+ id,
803
+ encodedList: statusList.compressStatusList(),
804
+ issuer,
805
+ type: StatusListType3.OAuthStatusList,
806
+ proofFormat,
807
+ length: statusList.statusList.length,
808
+ statusListCredential,
809
+ statuslistContentType: this.buildContentType(proofFormat),
810
+ correlationId,
811
+ driverType,
812
+ bitsPerStatus,
813
+ ...expiresAt && {
814
+ expiresAt
815
+ },
816
+ oauthStatusList: {
817
+ bitsPerStatus,
818
+ ...expiresAt && {
819
+ expiresAt
820
+ }
821
+ }
822
+ };
823
+ } else {
824
+ const { extractedDetails, statusListEntity } = args;
825
+ const oauthEntity = statusListEntity;
826
+ const decoded = extractedDetails.decodedPayload;
827
+ const proofFormat = determineProofFormat(statusListEntity.statusListCredential);
828
+ const expiresAt = decoded.exp ? new Date(decoded.exp * 1e3) : void 0;
829
+ return {
830
+ id: extractedDetails.id,
831
+ encodedList: extractedDetails.encodedList,
832
+ issuer: extractedDetails.issuer,
833
+ type: StatusListType3.OAuthStatusList,
834
+ proofFormat,
835
+ length: decoded.statusList.statusList.length,
836
+ statusListCredential: statusListEntity.statusListCredential,
837
+ statuslistContentType: this.buildContentType(proofFormat),
838
+ correlationId: statusListEntity.correlationId,
839
+ driverType: statusListEntity.driverType,
840
+ bitsPerStatus: oauthEntity.bitsPerStatus,
841
+ ...expiresAt && {
842
+ expiresAt
843
+ },
844
+ oauthStatusList: {
845
+ bitsPerStatus: oauthEntity.bitsPerStatus,
846
+ ...expiresAt && {
847
+ expiresAt
848
+ }
849
+ }
850
+ };
851
+ }
852
+ }
853
+ async createCredentialStatus(args) {
854
+ const { statusList, statusListIndex } = args;
855
+ const oauthStatusList = statusList;
856
+ return {
857
+ id: `${statusList.id}#${statusListIndex}`,
858
+ type: "OAuthStatusListEntry",
859
+ bitsPerStatus: oauthStatusList.bitsPerStatus,
860
+ statusListIndex: "" + statusListIndex,
861
+ statusListCredential: statusList.id,
862
+ expiresAt: oauthStatusList.expiresAt
727
863
  };
728
864
  }
865
+ buildContentType(proofFormat) {
866
+ return `application/statuslist+${proofFormat === "cbor" ? "cwt" : "jwt"}`;
867
+ }
729
868
  async createSignedStatusList(proofFormat, context, statusList, issuerString, id, expiresAt, keyRef) {
730
869
  switch (proofFormat) {
731
870
  case "jwt": {
@@ -747,12 +886,19 @@ import { StatusListType as StatusListType5 } from "@sphereon/ssi-types";
747
886
  import { CredentialMapper as CredentialMapper3, DocumentFormat as DocumentFormat3, StatusListType as StatusListType4 } from "@sphereon/ssi-types";
748
887
  import { BitstreamStatusList, createStatusListCredential } from "@4sure-tech/vc-bitstring-status-lists";
749
888
  var DEFAULT_LIST_LENGTH3 = 131072;
750
- var DEFAULT_PROOF_FORMAT3 = "lds";
889
+ var DEFAULT_PROOF_FORMAT3 = "vc+jwt";
751
890
  var DEFAULT_STATUS_PURPOSE = "revocation";
752
891
  var BitstringStatusListImplementation = class {
753
892
  static {
754
893
  __name(this, "BitstringStatusListImplementation");
755
894
  }
895
+ /**
896
+ * Creates a new bitstring status list with the specified configuration
897
+ *
898
+ * @param args - Configuration for the new status list including issuer, purpose, and size
899
+ * @param context - Veramo agent context for credential operations
900
+ * @returns Promise resolving to the created status list details
901
+ */
756
902
  async createNewStatusList(args, context) {
757
903
  if (!args.bitstringStatusList) {
758
904
  throw new Error("BitstringStatusList options are required for type BitstringStatusList");
@@ -760,28 +906,34 @@ var BitstringStatusListImplementation = class {
760
906
  const length = args?.length ?? DEFAULT_LIST_LENGTH3;
761
907
  const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT3;
762
908
  assertValidProofType(StatusListType4.BitstringStatusList, proofFormat);
763
- const veramoProofFormat = proofFormat;
764
909
  const { issuer, id } = args;
765
910
  const correlationId = getAssertedValue("correlationId", args.correlationId);
766
911
  const { statusPurpose, bitsPerStatus, validFrom, validUntil, ttl } = args.bitstringStatusList;
767
- const statusListCredential = await this.createVerifiableCredential({
768
- ...args,
769
- proofFormat: veramoProofFormat,
912
+ const unsignedCredential = await createStatusListCredential({
913
+ id,
914
+ issuer,
770
915
  statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
771
916
  validFrom: ensureDate(validFrom),
772
917
  validUntil: ensureDate(validUntil),
773
918
  ttl
919
+ });
920
+ const statusListCredential = await this.createVerifiableCredential({
921
+ unsignedCredential,
922
+ id,
923
+ issuer,
924
+ proofFormat,
925
+ keyRef: args.keyRef
774
926
  }, context);
775
927
  return {
776
- encodedList: statusListCredential.credentialSubject.encodedList,
928
+ encodedList: unsignedCredential.credentialSubject.encodedList,
777
929
  statusListCredential,
778
930
  bitstringStatusList: {
779
931
  statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
780
- ...statusListCredential.validFrom && {
781
- validFrom: new Date(statusListCredential.validFrom)
932
+ ...unsignedCredential.validFrom && {
933
+ validFrom: new Date(unsignedCredential.validFrom)
782
934
  },
783
- ...statusListCredential.validUntil && {
784
- validUntil: new Date(statusListCredential.validUntil)
935
+ ...unsignedCredential.validUntil && {
936
+ validUntil: new Date(unsignedCredential.validUntil)
785
937
  },
786
938
  ttl,
787
939
  bitsPerStatus
@@ -795,9 +947,16 @@ var BitstringStatusListImplementation = class {
795
947
  statuslistContentType: this.buildContentType(proofFormat)
796
948
  };
797
949
  }
950
+ /**
951
+ * Updates the status of a specific credential in an existing status list
952
+ *
953
+ * @param args - Update parameters including the status list credential, index, and new value
954
+ * @param context - Veramo agent context for credential operations
955
+ * @returns Promise resolving to the updated status list details
956
+ */
798
957
  async updateStatusListIndex(args, context) {
799
958
  if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
800
- return Promise.reject("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListIndex)");
959
+ return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListIndex)"));
801
960
  }
802
961
  const credential = args.statusListCredential;
803
962
  const uniform = CredentialMapper3.toUniformCredential(credential);
@@ -809,34 +968,40 @@ var BitstringStatusListImplementation = class {
809
968
  encodedList: origEncodedList,
810
969
  statusSize: args.bitsPerStatus
811
970
  });
812
- statusList.setStatus(index, args.value);
813
- const proofFormat = CredentialMapper3.detectDocumentType(credential) === DocumentFormat3.JWT ? "jwt" : "lds";
971
+ const bitstringStatusId = args.value;
972
+ statusList.setStatus(index, bitstringStatusId);
973
+ const proofFormat = CredentialMapper3.detectDocumentType(credential) === DocumentFormat3.JWT ? "vc+jwt" : "lds";
814
974
  const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
815
975
  const statusPurpose = getAssertedProperty("statusPurpose", credSubject);
816
976
  const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : void 0;
817
977
  const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : void 0;
818
978
  const ttl = credSubject.ttl;
819
- const updatedCredential = await this.createVerifiableCredential({
820
- ...args,
979
+ const unsignedCredential = await createStatusListCredential({
821
980
  id,
822
981
  issuer,
823
982
  statusList,
983
+ statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
984
+ validFrom: ensureDate(validFrom),
985
+ validUntil: ensureDate(validUntil),
986
+ ttl
987
+ });
988
+ const updatedCredential = await this.createVerifiableCredential({
989
+ unsignedCredential,
990
+ id,
991
+ issuer,
824
992
  proofFormat,
825
- statusPurpose,
826
- ttl,
827
- validFrom,
828
- validUntil
993
+ keyRef: args.keyRef
829
994
  }, context);
830
995
  return {
831
996
  statusListCredential: updatedCredential,
832
- encodedList: updatedCredential.credentialSubject.encodedList,
997
+ encodedList: unsignedCredential.credentialSubject.encodedList,
833
998
  bitstringStatusList: {
834
999
  statusPurpose,
835
- ...updatedCredential.validFrom && {
836
- validFrom: new Date(updatedCredential.validFrom)
1000
+ ...unsignedCredential.validFrom && {
1001
+ validFrom: new Date(unsignedCredential.validFrom)
837
1002
  },
838
- ...updatedCredential.validUntil && {
839
- validUntil: new Date(updatedCredential.validUntil)
1003
+ ...unsignedCredential.validUntil && {
1004
+ validUntil: new Date(unsignedCredential.validUntil)
840
1005
  },
841
1006
  bitsPerStatus: args.bitsPerStatus,
842
1007
  ttl
@@ -849,17 +1014,23 @@ var BitstringStatusListImplementation = class {
849
1014
  statuslistContentType: this.buildContentType(proofFormat)
850
1015
  };
851
1016
  }
1017
+ /**
1018
+ * Updates a status list by decoding an encoded list, modifying it, and re-encoding
1019
+ *
1020
+ * @param args - Update parameters including encoded list, index, and new value
1021
+ * @param context - Veramo agent context for credential operations
1022
+ * @returns Promise resolving to the updated status list details
1023
+ */
852
1024
  async updateStatusListFromEncodedList(args, context) {
853
1025
  if (!args.bitstringStatusList) {
854
1026
  throw new Error("bitstringStatusList options required for type BitstringStatusList");
855
1027
  }
856
1028
  if (args.bitstringStatusList.bitsPerStatus < 1) {
857
- return Promise.reject("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListFromEncodedList)");
1029
+ return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (updateStatusListFromEncodedList)"));
858
1030
  }
859
1031
  const { statusPurpose, bitsPerStatus, ttl, validFrom, validUntil } = args.bitstringStatusList;
860
1032
  const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT3;
861
1033
  assertValidProofType(StatusListType4.BitstringStatusList, proofFormat);
862
- const veramoProofFormat = proofFormat;
863
1034
  const { issuer, id } = getAssertedValues(args);
864
1035
  const statusList = await BitstreamStatusList.decode({
865
1036
  encodedList: args.encodedList,
@@ -867,29 +1038,34 @@ var BitstringStatusListImplementation = class {
867
1038
  });
868
1039
  const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
869
1040
  statusList.setStatus(index, args.value);
870
- const credential = await this.createVerifiableCredential({
1041
+ const unsignedCredential = await createStatusListCredential({
871
1042
  id,
872
1043
  issuer,
873
1044
  statusList,
874
- proofFormat: veramoProofFormat,
875
- keyRef: args.keyRef,
876
- statusPurpose,
1045
+ statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
877
1046
  validFrom: ensureDate(validFrom),
878
1047
  validUntil: ensureDate(validUntil),
879
1048
  ttl
1049
+ });
1050
+ const credential = await this.createVerifiableCredential({
1051
+ unsignedCredential,
1052
+ id,
1053
+ issuer,
1054
+ proofFormat,
1055
+ keyRef: args.keyRef
880
1056
  }, context);
881
1057
  return {
882
1058
  type: StatusListType4.BitstringStatusList,
883
1059
  statusListCredential: credential,
884
- encodedList: credential.credentialSubject.encodedList,
1060
+ encodedList: unsignedCredential.credentialSubject.encodedList,
885
1061
  bitstringStatusList: {
886
1062
  statusPurpose,
887
1063
  bitsPerStatus,
888
- ...credential.validFrom && {
889
- validFrom: new Date(credential.validFrom)
1064
+ ...unsignedCredential.validFrom && {
1065
+ validFrom: new Date(unsignedCredential.validFrom)
890
1066
  },
891
- ...credential.validUntil && {
892
- validUntil: new Date(credential.validUntil)
1067
+ ...unsignedCredential.validUntil && {
1068
+ validUntil: new Date(unsignedCredential.validUntil)
893
1069
  },
894
1070
  ttl
895
1071
  },
@@ -900,17 +1076,22 @@ var BitstringStatusListImplementation = class {
900
1076
  statuslistContentType: this.buildContentType(proofFormat)
901
1077
  };
902
1078
  }
1079
+ /**
1080
+ * Checks the status of a specific credential by its index in the status list
1081
+ *
1082
+ * @param args - Check parameters including the status list credential and index
1083
+ * @returns Promise resolving to the status value at the specified index
1084
+ */
903
1085
  async checkStatusIndex(args) {
904
1086
  if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
905
- return Promise.reject("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (checkStatusIndex)");
1087
+ return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (checkStatusIndex)"));
906
1088
  }
907
1089
  const uniform = CredentialMapper3.toUniformCredential(args.statusListCredential);
908
1090
  const { credentialSubject } = uniform;
909
1091
  const encodedList = getAssertedProperty("encodedList", credentialSubject);
910
- const statusSize = args.bitsPerStatus;
911
1092
  const statusList = await BitstreamStatusList.decode({
912
1093
  encodedList,
913
- statusSize
1094
+ statusSize: args.bitsPerStatus
914
1095
  });
915
1096
  const numIndex = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
916
1097
  if (statusList.getLength() <= numIndex) {
@@ -918,67 +1099,177 @@ var BitstringStatusListImplementation = class {
918
1099
  }
919
1100
  return statusList.getStatus(numIndex);
920
1101
  }
921
- async toStatusListDetails(args) {
922
- const { statusListPayload, bitsPerStatus } = args;
923
- if (!bitsPerStatus || bitsPerStatus < 1) {
924
- return Promise.reject("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (toStatusListDetails)");
925
- }
926
- const uniform = CredentialMapper3.toUniformCredential(statusListPayload);
1102
+ /**
1103
+ * Performs the initial parsing of a StatusListCredential.
1104
+ * This method handles expensive operations like JWT/CWT decoding once.
1105
+ * It extracts all details available from the credential payload itself.
1106
+ */
1107
+ async extractCredentialDetails(credential) {
1108
+ const uniform = CredentialMapper3.toUniformCredential(credential);
927
1109
  const { issuer, credentialSubject } = uniform;
928
- const id = getAssertedValue("id", uniform.id);
929
- const encodedList = getAssertedProperty("encodedList", credentialSubject);
930
- const proofFormat = CredentialMapper3.detectDocumentType(statusListPayload) === DocumentFormat3.JWT ? "jwt" : "lds";
931
- const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
932
- const statusPurpose = getAssertedProperty("statusPurpose", credSubject);
933
- const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : void 0;
934
- const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : void 0;
935
- const ttl = credSubject.ttl;
936
- const statuslistLength = BitstreamStatusList.getStatusListLength(encodedList, bitsPerStatus);
1110
+ const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
937
1111
  return {
938
- id,
939
- encodedList,
1112
+ id: getAssertedValue("id", uniform.id),
940
1113
  issuer,
941
- type: StatusListType4.BitstringStatusList,
942
- proofFormat,
943
- length: statuslistLength,
944
- statusListCredential: statusListPayload,
945
- statuslistContentType: this.buildContentType(proofFormat),
946
- bitstringStatusList: {
1114
+ encodedList: getAssertedProperty("encodedList", subject)
1115
+ };
1116
+ }
1117
+ async toStatusListDetails(args) {
1118
+ if ("statusListCredential" in args) {
1119
+ const { statusListCredential, bitsPerStatus, correlationId, driverType } = args;
1120
+ if (!bitsPerStatus || bitsPerStatus < 1) {
1121
+ return Promise.reject(Error("bitsPerStatus must be set for bitstring status lists and must be 1 or higher"));
1122
+ }
1123
+ const uniform = CredentialMapper3.toUniformCredential(statusListCredential);
1124
+ const { issuer, credentialSubject } = uniform;
1125
+ const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
1126
+ const id = getAssertedValue("id", uniform.id);
1127
+ const encodedList = getAssertedProperty("encodedList", subject);
1128
+ const statusPurpose = getAssertedProperty("statusPurpose", subject);
1129
+ const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : void 0;
1130
+ const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : void 0;
1131
+ const ttl = subject.ttl;
1132
+ const proofFormat = CredentialMapper3.detectDocumentType(statusListCredential) === DocumentFormat3.JWT ? "vc+jwt" : "lds";
1133
+ const statuslistLength = BitstreamStatusList.getStatusListLength(encodedList, bitsPerStatus);
1134
+ return {
1135
+ id,
1136
+ encodedList,
1137
+ issuer,
1138
+ type: StatusListType4.BitstringStatusList,
1139
+ proofFormat,
1140
+ length: statuslistLength,
1141
+ statusListCredential,
1142
+ statuslistContentType: this.buildContentType(proofFormat),
1143
+ correlationId,
1144
+ driverType,
947
1145
  statusPurpose,
948
1146
  bitsPerStatus,
949
- validFrom,
950
- validUntil,
951
- ttl
952
- },
953
- ...args.correlationId && {
954
- correlationId: args.correlationId
955
- },
956
- ...args.driverType && {
957
- driverType: args.driverType
1147
+ ...validFrom && {
1148
+ validFrom
1149
+ },
1150
+ ...validUntil && {
1151
+ validUntil
1152
+ },
1153
+ ...ttl && {
1154
+ ttl
1155
+ },
1156
+ bitstringStatusList: {
1157
+ statusPurpose,
1158
+ bitsPerStatus,
1159
+ ...validFrom && {
1160
+ validFrom
1161
+ },
1162
+ ...validUntil && {
1163
+ validUntil
1164
+ },
1165
+ ...ttl && {
1166
+ ttl
1167
+ }
1168
+ }
1169
+ };
1170
+ } else {
1171
+ const { extractedDetails, statusListEntity } = args;
1172
+ const bitstringEntity = statusListEntity;
1173
+ if (!bitstringEntity.bitsPerStatus) {
1174
+ return Promise.reject(Error("bitsPerStatus must be present for a bitstring status list"));
958
1175
  }
1176
+ const proofFormat = CredentialMapper3.detectDocumentType(statusListEntity.statusListCredential) === DocumentFormat3.JWT ? "vc+jwt" : "lds";
1177
+ const statuslistLength = BitstreamStatusList.getStatusListLength(extractedDetails.encodedList, bitstringEntity.bitsPerStatus);
1178
+ return {
1179
+ id: extractedDetails.id,
1180
+ encodedList: extractedDetails.encodedList,
1181
+ issuer: extractedDetails.issuer,
1182
+ type: StatusListType4.BitstringStatusList,
1183
+ proofFormat,
1184
+ length: statuslistLength,
1185
+ statusListCredential: statusListEntity.statusListCredential,
1186
+ statuslistContentType: this.buildContentType(proofFormat),
1187
+ correlationId: statusListEntity.correlationId,
1188
+ driverType: statusListEntity.driverType,
1189
+ statusPurpose: bitstringEntity.statusPurpose,
1190
+ bitsPerStatus: bitstringEntity.bitsPerStatus,
1191
+ ...bitstringEntity.validFrom && {
1192
+ validFrom: bitstringEntity.validFrom
1193
+ },
1194
+ ...bitstringEntity.validUntil && {
1195
+ validUntil: bitstringEntity.validUntil
1196
+ },
1197
+ ...bitstringEntity.ttl && {
1198
+ ttl: bitstringEntity.ttl
1199
+ },
1200
+ bitstringStatusList: {
1201
+ statusPurpose: bitstringEntity.statusPurpose,
1202
+ bitsPerStatus: bitstringEntity.bitsPerStatus,
1203
+ ...bitstringEntity.validFrom && {
1204
+ validFrom: bitstringEntity.validFrom
1205
+ },
1206
+ ...bitstringEntity.validUntil && {
1207
+ validUntil: bitstringEntity.validUntil
1208
+ },
1209
+ ...bitstringEntity.ttl && {
1210
+ ttl: bitstringEntity.ttl
1211
+ }
1212
+ }
1213
+ };
1214
+ }
1215
+ }
1216
+ /**
1217
+ * Creates a credential status entry for a specific credential in a status list
1218
+ *
1219
+ * @param args - Parameters including the status list, entry details, and index
1220
+ * @returns Promise resolving to the credential status entry
1221
+ */
1222
+ async createCredentialStatus(args) {
1223
+ const { statusList, statusListEntry, statusListIndex } = args;
1224
+ const bitstringStatusList = statusList;
1225
+ const bitstringStatusListEntry = statusListEntry;
1226
+ return {
1227
+ id: `${statusList.id}#${statusListIndex}`,
1228
+ type: "BitstringStatusListEntry",
1229
+ statusPurpose: bitstringStatusListEntry.statusPurpose,
1230
+ statusListIndex: "" + statusListIndex,
1231
+ statusListCredential: statusList.id,
1232
+ bitsPerStatus: bitstringStatusList.bitsPerStatus,
1233
+ statusMessage: bitstringStatusListEntry.statusMessage,
1234
+ statusReference: bitstringStatusListEntry.statusReference
959
1235
  };
960
1236
  }
1237
+ /**
1238
+ * Creates a signed verifiable credential from an unsigned status list credential
1239
+ *
1240
+ * @param args - Parameters including the unsigned credential and signing details
1241
+ * @param context - Veramo agent context for credential operations
1242
+ * @returns Promise resolving to the signed credential
1243
+ */
961
1244
  async createVerifiableCredential(args, context) {
1245
+ const { unsignedCredential, issuer, proofFormat, keyRef } = args;
962
1246
  const identifier = await context.agent.identifierManagedGet({
963
- identifier: typeof args.issuer === "string" ? args.issuer : args.issuer.id,
1247
+ identifier: typeof issuer === "string" ? issuer : issuer.id,
964
1248
  vmRelationship: "assertionMethod",
965
1249
  offlineWhenNoDIDRegistered: true
966
1250
  });
967
- const unsignedCredential = await createStatusListCredential(args);
968
1251
  const verifiableCredential = await context.agent.createVerifiableCredential({
969
1252
  credential: unsignedCredential,
970
- keyRef: args.keyRef ?? identifier.kmsKeyRef,
971
- proofFormat: args.proofFormat,
1253
+ keyRef: keyRef ?? identifier.kmsKeyRef,
1254
+ proofFormat,
972
1255
  fetchRemoteContexts: true
973
1256
  });
974
1257
  return CredentialMapper3.toWrappedVerifiableCredential(verifiableCredential).original;
975
1258
  }
1259
+ /**
1260
+ * Builds the appropriate content type string for a given proof format
1261
+ *
1262
+ * @param proofFormat - The proof format to build content type for
1263
+ * @returns The corresponding content type string
1264
+ */
976
1265
  buildContentType(proofFormat) {
977
1266
  switch (proofFormat) {
978
1267
  case "jwt":
979
- return `application/statuslist+jwt`;
1268
+ return "application/statuslist+jwt";
980
1269
  case "cbor":
981
- return `application/statuslist+cwt`;
1270
+ return "application/statuslist+cwt";
1271
+ case "vc+jwt":
1272
+ return "application/statuslist+vc+jwt";
982
1273
  case "lds":
983
1274
  return "application/statuslist+ld+json";
984
1275
  default:
@@ -1134,36 +1425,35 @@ async function updateStatusIndexFromStatusListCredential(args, context) {
1134
1425
  return implementation.updateStatusListIndex(args, context);
1135
1426
  }
1136
1427
  __name(updateStatusIndexFromStatusListCredential, "updateStatusIndexFromStatusListCredential");
1137
- async function statusListCredentialToDetails({ correlationId, driverType, statusListCredential, bitsPerStatus }) {
1138
- const credential = getAssertedValue("statusListCredential", statusListCredential);
1139
- let statusListType;
1140
- const documentFormat = CredentialMapper4.detectDocumentType(credential);
1141
- if (documentFormat === DocumentFormat4.JWT) {
1142
- const [header] = credential.split(".");
1143
- const decodedHeader = JSON.parse(Buffer.from(header, "base64").toString());
1144
- if (decodedHeader.typ === "statuslist+jwt") {
1145
- statusListType = StatusListType6.OAuthStatusList;
1146
- }
1147
- } else if (documentFormat === DocumentFormat4.MSO_MDOC) {
1148
- statusListType = StatusListType6.OAuthStatusList;
1149
- }
1150
- if (!statusListType) {
1151
- const uniform = CredentialMapper4.toUniformCredential(credential);
1152
- const type = uniform.type.find((t) => t.includes("StatusList2021") || t.includes("OAuth2StatusList") || t.includes("BitstringStatusList"));
1153
- if (!type) {
1154
- throw new Error("Invalid status list credential type");
1155
- }
1156
- statusListType = type.replace("Credential", "");
1428
+ async function extractCredentialDetails(statusListCredential) {
1429
+ const statusListType = determineStatusListType(statusListCredential);
1430
+ const implementation = getStatusListImplementation(statusListType);
1431
+ return implementation.extractCredentialDetails(statusListCredential);
1432
+ }
1433
+ __name(extractCredentialDetails, "extractCredentialDetails");
1434
+ async function toStatusListDetails(args) {
1435
+ if ("statusListCredential" in args) {
1436
+ const statusListType = args.statusListType;
1437
+ const implementation = getStatusListImplementation(statusListType);
1438
+ return implementation.toStatusListDetails(args);
1439
+ } else {
1440
+ const statusListType = args.statusListEntity.type;
1441
+ const implementation = getStatusListImplementation(statusListType);
1442
+ return implementation.toStatusListDetails(args);
1157
1443
  }
1444
+ }
1445
+ __name(toStatusListDetails, "toStatusListDetails");
1446
+ async function createCredentialStatusFromStatusList(args) {
1447
+ const { statusList, statusListEntry, statusListIndex } = args;
1448
+ const statusListType = determineStatusListType(statusList.statusListCredential);
1158
1449
  const implementation = getStatusListImplementation(statusListType);
1159
- return await implementation.toStatusListDetails({
1160
- statusListPayload: credential,
1161
- correlationId,
1162
- driverType,
1163
- bitsPerStatus
1450
+ return implementation.createCredentialStatus({
1451
+ statusList,
1452
+ statusListEntry,
1453
+ statusListIndex
1164
1454
  });
1165
1455
  }
1166
- __name(statusListCredentialToDetails, "statusListCredentialToDetails");
1456
+ __name(createCredentialStatusFromStatusList, "createCredentialStatusFromStatusList");
1167
1457
  async function updateStatusListIndexFromEncodedList(args, context) {
1168
1458
  const { type } = getAssertedValue("type", args);
1169
1459
  const implementation = getStatusListImplementation(type);
@@ -1215,12 +1505,15 @@ export {
1215
1505
  StatusOAuth,
1216
1506
  checkStatusForCredential,
1217
1507
  checkStatusIndexFromStatusListCredential,
1508
+ createCredentialStatusFromStatusList,
1218
1509
  createNewStatusList,
1510
+ determineStatusListType,
1511
+ extractCredentialDetails,
1219
1512
  fetchStatusListCredential,
1220
1513
  simpleCheckStatusFromStatusListUrl,
1221
1514
  statusList2021ToVerifiableCredential,
1222
- statusListCredentialToDetails,
1223
1515
  statusPluginStatusFunction,
1516
+ toStatusListDetails,
1224
1517
  updateStatusIndexFromStatusListCredential,
1225
1518
  updateStatusListIndexFromEncodedList,
1226
1519
  vcLibCheckStatusFunction