@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.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) {
@@ -257,13 +282,14 @@ var StatusList2021Implementation = class {
257
282
  encodedList,
258
283
  proofFormat
259
284
  }, context);
285
+ if (!("statusPurpose" in credentialSubject)) {
286
+ return Promise.reject(Error("statusPurpose is required in credentialSubject for StatusList2021"));
287
+ }
260
288
  return {
261
289
  statusListCredential: updatedCredential,
262
290
  encodedList,
263
291
  statusList2021: {
264
- ..."statusPurpose" in credentialSubject ? {
265
- statusPurpose: credentialSubject.statusPurpose
266
- } : {},
292
+ statusPurpose: credentialSubject.statusPurpose,
267
293
  indexingDirection: "rightToLeft"
268
294
  },
269
295
  length: statusList.length - 1,
@@ -320,36 +346,88 @@ var StatusList2021Implementation = class {
320
346
  const status = statusList.getStatus(typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex));
321
347
  return status ? Status2021.Invalid : Status2021.Valid;
322
348
  }
323
- async toStatusListDetails(args) {
324
- const { statusListPayload } = args;
325
- 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);
326
356
  const { issuer, credentialSubject } = uniform;
327
- const id = getAssertedValue("id", uniform.id);
328
- const encodedList = getAssertedProperty("encodedList", credentialSubject);
329
- const proofFormat = import_ssi_types2.CredentialMapper.detectDocumentType(statusListPayload) === import_ssi_types2.DocumentFormat.JWT ? "jwt" : "lds";
330
- const statusPurpose = getAssertedProperty("statusPurpose", credentialSubject);
331
- const list = await import_vc_status_list.StatusList.decode({
332
- encodedList
333
- });
357
+ const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
334
358
  return {
335
- id,
336
- encodedList,
359
+ id: getAssertedValue("id", uniform.id),
337
360
  issuer,
338
- type: import_ssi_types2.StatusListType.StatusList2021,
339
- proofFormat,
340
- length: list.length,
341
- statusListCredential: statusListPayload,
342
- statuslistContentType: this.buildContentType(proofFormat),
343
- 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,
344
388
  indexingDirection: "rightToLeft",
345
- statusPurpose
346
- },
347
- ...args.correlationId && {
348
- correlationId: args.correlationId
349
- },
350
- ...args.driverType && {
351
- driverType: args.driverType
352
- }
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
353
431
  };
354
432
  }
355
433
  async createVerifiableCredential(args, context) {
@@ -643,9 +721,9 @@ var OAuthStatusListImplementation = class {
643
721
  throw new Error("OAuthStatusList options are required for type OAuthStatusList");
644
722
  }
645
723
  const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT2;
646
- const { issuer, id, oauthStatusList: oauthStatusList1, keyRef } = args;
647
- const { bitsPerStatus } = oauthStatusList1;
648
- const expiresAt = ensureDate(oauthStatusList1.expiresAt);
724
+ const { issuer, id, oauthStatusList, keyRef } = args;
725
+ const { bitsPerStatus } = oauthStatusList;
726
+ const expiresAt = ensureDate(oauthStatusList.expiresAt);
649
727
  const length = args.length ?? DEFAULT_LIST_LENGTH2;
650
728
  const issuerString = typeof issuer === "string" ? issuer : issuer.id;
651
729
  const correlationId = getAssertedValue("correlationId", args.correlationId);
@@ -669,7 +747,7 @@ var OAuthStatusListImplementation = class {
669
747
  }
670
748
  async updateStatusListIndex(args, context) {
671
749
  const { statusListCredential, value, keyRef } = args;
672
- const expiresAt = ensureDate(oauthStatusList.expiresAt);
750
+ const expiresAt = ensureDate(args.expiresAt);
673
751
  if (typeof statusListCredential !== "string") {
674
752
  return Promise.reject("statusListCredential in neither JWT nor CWT");
675
753
  }
@@ -704,9 +782,9 @@ var OAuthStatusListImplementation = class {
704
782
  if (!args.oauthStatusList) {
705
783
  throw new Error("OAuthStatusList options are required for type OAuthStatusList");
706
784
  }
707
- const { proofFormat, oauthStatusList: oauthStatusList1, keyRef } = args;
708
- const { bitsPerStatus } = oauthStatusList1;
709
- const expiresAt = ensureDate(oauthStatusList1.expiresAt);
785
+ const { proofFormat, oauthStatusList, keyRef } = args;
786
+ const { bitsPerStatus } = oauthStatusList;
787
+ const expiresAt = ensureDate(oauthStatusList.expiresAt);
710
788
  const { issuer, id } = getAssertedValues(args);
711
789
  const issuerString = typeof issuer === "string" ? issuer : issuer.id;
712
790
  const listToUpdate = import_jwt_status_list3.StatusList.decompressStatusList(args.encodedList, bitsPerStatus ?? DEFAULT_BITS_PER_STATUS);
@@ -728,9 +806,6 @@ var OAuthStatusListImplementation = class {
728
806
  statuslistContentType: this.buildContentType(proofFormat)
729
807
  };
730
808
  }
731
- buildContentType(proofFormat) {
732
- return `application/statuslist+${proofFormat === "cbor" ? "cwt" : "jwt"}`;
733
- }
734
809
  async checkStatusIndex(args) {
735
810
  const { statusListCredential, statusListIndex } = args;
736
811
  if (typeof statusListCredential !== "string") {
@@ -744,34 +819,101 @@ var OAuthStatusListImplementation = class {
744
819
  }
745
820
  return statusList.getStatus(index);
746
821
  }
747
- async toStatusListDetails(args) {
748
- const { statusListPayload } = args;
749
- const proofFormat = determineProofFormat(statusListPayload);
750
- const decoded = proofFormat === "jwt" ? decodeStatusListJWT(statusListPayload) : decodeStatusListCWT(statusListPayload);
751
- 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);
752
833
  return {
753
- id,
754
- encodedList: statusList.compressStatusList(),
755
- issuer,
756
- type: import_ssi_types4.StatusListType.OAuthStatusList,
757
- proofFormat,
758
- length: statusList.statusList.length,
759
- statusListCredential: statusListPayload,
760
- statuslistContentType: this.buildContentType(proofFormat),
761
- oauthStatusList: {
762
- bitsPerStatus: statusList.getBitsPerStatus(),
763
- ...exp && {
764
- expiresAt: new Date(exp * 1e3)
765
- }
766
- },
767
- ...args.correlationId && {
768
- correlationId: args.correlationId
769
- },
770
- ...args.driverType && {
771
- 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"));
772
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
773
912
  };
774
913
  }
914
+ buildContentType(proofFormat) {
915
+ return `application/statuslist+${proofFormat === "cbor" ? "cwt" : "jwt"}`;
916
+ }
775
917
  async createSignedStatusList(proofFormat, context, statusList, issuerString, id, expiresAt, keyRef) {
776
918
  switch (proofFormat) {
777
919
  case "jwt": {
@@ -793,12 +935,19 @@ var import_ssi_types6 = require("@sphereon/ssi-types");
793
935
  var import_ssi_types5 = require("@sphereon/ssi-types");
794
936
  var import_vc_bitstring_status_lists = require("@4sure-tech/vc-bitstring-status-lists");
795
937
  var DEFAULT_LIST_LENGTH3 = 131072;
796
- var DEFAULT_PROOF_FORMAT3 = "lds";
938
+ var DEFAULT_PROOF_FORMAT3 = "vc+jwt";
797
939
  var DEFAULT_STATUS_PURPOSE = "revocation";
798
940
  var BitstringStatusListImplementation = class {
799
941
  static {
800
942
  __name(this, "BitstringStatusListImplementation");
801
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
+ */
802
951
  async createNewStatusList(args, context) {
803
952
  if (!args.bitstringStatusList) {
804
953
  throw new Error("BitstringStatusList options are required for type BitstringStatusList");
@@ -806,28 +955,34 @@ var BitstringStatusListImplementation = class {
806
955
  const length = args?.length ?? DEFAULT_LIST_LENGTH3;
807
956
  const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT3;
808
957
  assertValidProofType(import_ssi_types5.StatusListType.BitstringStatusList, proofFormat);
809
- const veramoProofFormat = proofFormat;
810
958
  const { issuer, id } = args;
811
959
  const correlationId = getAssertedValue("correlationId", args.correlationId);
812
960
  const { statusPurpose, bitsPerStatus, validFrom, validUntil, ttl } = args.bitstringStatusList;
813
- const statusListCredential = await this.createVerifiableCredential({
814
- ...args,
815
- proofFormat: veramoProofFormat,
961
+ const unsignedCredential = await (0, import_vc_bitstring_status_lists.createStatusListCredential)({
962
+ id,
963
+ issuer,
816
964
  statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
817
965
  validFrom: ensureDate(validFrom),
818
966
  validUntil: ensureDate(validUntil),
819
967
  ttl
968
+ });
969
+ const statusListCredential = await this.createVerifiableCredential({
970
+ unsignedCredential,
971
+ id,
972
+ issuer,
973
+ proofFormat,
974
+ keyRef: args.keyRef
820
975
  }, context);
821
976
  return {
822
- encodedList: statusListCredential.credentialSubject.encodedList,
977
+ encodedList: unsignedCredential.credentialSubject.encodedList,
823
978
  statusListCredential,
824
979
  bitstringStatusList: {
825
980
  statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
826
- ...statusListCredential.validFrom && {
827
- validFrom: new Date(statusListCredential.validFrom)
981
+ ...unsignedCredential.validFrom && {
982
+ validFrom: new Date(unsignedCredential.validFrom)
828
983
  },
829
- ...statusListCredential.validUntil && {
830
- validUntil: new Date(statusListCredential.validUntil)
984
+ ...unsignedCredential.validUntil && {
985
+ validUntil: new Date(unsignedCredential.validUntil)
831
986
  },
832
987
  ttl,
833
988
  bitsPerStatus
@@ -841,9 +996,16 @@ var BitstringStatusListImplementation = class {
841
996
  statuslistContentType: this.buildContentType(proofFormat)
842
997
  };
843
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
+ */
844
1006
  async updateStatusListIndex(args, context) {
845
1007
  if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
846
- 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)"));
847
1009
  }
848
1010
  const credential = args.statusListCredential;
849
1011
  const uniform = import_ssi_types5.CredentialMapper.toUniformCredential(credential);
@@ -855,34 +1017,40 @@ var BitstringStatusListImplementation = class {
855
1017
  encodedList: origEncodedList,
856
1018
  statusSize: args.bitsPerStatus
857
1019
  });
858
- statusList.setStatus(index, args.value);
859
- 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";
860
1023
  const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
861
1024
  const statusPurpose = getAssertedProperty("statusPurpose", credSubject);
862
1025
  const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : void 0;
863
1026
  const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : void 0;
864
1027
  const ttl = credSubject.ttl;
865
- const updatedCredential = await this.createVerifiableCredential({
866
- ...args,
1028
+ const unsignedCredential = await (0, import_vc_bitstring_status_lists.createStatusListCredential)({
867
1029
  id,
868
1030
  issuer,
869
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,
870
1041
  proofFormat,
871
- statusPurpose,
872
- ttl,
873
- validFrom,
874
- validUntil
1042
+ keyRef: args.keyRef
875
1043
  }, context);
876
1044
  return {
877
1045
  statusListCredential: updatedCredential,
878
- encodedList: updatedCredential.credentialSubject.encodedList,
1046
+ encodedList: unsignedCredential.credentialSubject.encodedList,
879
1047
  bitstringStatusList: {
880
1048
  statusPurpose,
881
- ...updatedCredential.validFrom && {
882
- validFrom: new Date(updatedCredential.validFrom)
1049
+ ...unsignedCredential.validFrom && {
1050
+ validFrom: new Date(unsignedCredential.validFrom)
883
1051
  },
884
- ...updatedCredential.validUntil && {
885
- validUntil: new Date(updatedCredential.validUntil)
1052
+ ...unsignedCredential.validUntil && {
1053
+ validUntil: new Date(unsignedCredential.validUntil)
886
1054
  },
887
1055
  bitsPerStatus: args.bitsPerStatus,
888
1056
  ttl
@@ -895,17 +1063,23 @@ var BitstringStatusListImplementation = class {
895
1063
  statuslistContentType: this.buildContentType(proofFormat)
896
1064
  };
897
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
+ */
898
1073
  async updateStatusListFromEncodedList(args, context) {
899
1074
  if (!args.bitstringStatusList) {
900
1075
  throw new Error("bitstringStatusList options required for type BitstringStatusList");
901
1076
  }
902
1077
  if (args.bitstringStatusList.bitsPerStatus < 1) {
903
- 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)"));
904
1079
  }
905
1080
  const { statusPurpose, bitsPerStatus, ttl, validFrom, validUntil } = args.bitstringStatusList;
906
1081
  const proofFormat = args?.proofFormat ?? DEFAULT_PROOF_FORMAT3;
907
1082
  assertValidProofType(import_ssi_types5.StatusListType.BitstringStatusList, proofFormat);
908
- const veramoProofFormat = proofFormat;
909
1083
  const { issuer, id } = getAssertedValues(args);
910
1084
  const statusList = await import_vc_bitstring_status_lists.BitstreamStatusList.decode({
911
1085
  encodedList: args.encodedList,
@@ -913,29 +1087,34 @@ var BitstringStatusListImplementation = class {
913
1087
  });
914
1088
  const index = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
915
1089
  statusList.setStatus(index, args.value);
916
- const credential = await this.createVerifiableCredential({
1090
+ const unsignedCredential = await (0, import_vc_bitstring_status_lists.createStatusListCredential)({
917
1091
  id,
918
1092
  issuer,
919
1093
  statusList,
920
- proofFormat: veramoProofFormat,
921
- keyRef: args.keyRef,
922
- statusPurpose,
1094
+ statusPurpose: statusPurpose ?? DEFAULT_STATUS_PURPOSE,
923
1095
  validFrom: ensureDate(validFrom),
924
1096
  validUntil: ensureDate(validUntil),
925
1097
  ttl
1098
+ });
1099
+ const credential = await this.createVerifiableCredential({
1100
+ unsignedCredential,
1101
+ id,
1102
+ issuer,
1103
+ proofFormat,
1104
+ keyRef: args.keyRef
926
1105
  }, context);
927
1106
  return {
928
1107
  type: import_ssi_types5.StatusListType.BitstringStatusList,
929
1108
  statusListCredential: credential,
930
- encodedList: credential.credentialSubject.encodedList,
1109
+ encodedList: unsignedCredential.credentialSubject.encodedList,
931
1110
  bitstringStatusList: {
932
1111
  statusPurpose,
933
1112
  bitsPerStatus,
934
- ...credential.validFrom && {
935
- validFrom: new Date(credential.validFrom)
1113
+ ...unsignedCredential.validFrom && {
1114
+ validFrom: new Date(unsignedCredential.validFrom)
936
1115
  },
937
- ...credential.validUntil && {
938
- validUntil: new Date(credential.validUntil)
1116
+ ...unsignedCredential.validUntil && {
1117
+ validUntil: new Date(unsignedCredential.validUntil)
939
1118
  },
940
1119
  ttl
941
1120
  },
@@ -946,17 +1125,22 @@ var BitstringStatusListImplementation = class {
946
1125
  statuslistContentType: this.buildContentType(proofFormat)
947
1126
  };
948
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
+ */
949
1134
  async checkStatusIndex(args) {
950
1135
  if (!args.bitsPerStatus || args.bitsPerStatus < 1) {
951
- 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)"));
952
1137
  }
953
1138
  const uniform = import_ssi_types5.CredentialMapper.toUniformCredential(args.statusListCredential);
954
1139
  const { credentialSubject } = uniform;
955
1140
  const encodedList = getAssertedProperty("encodedList", credentialSubject);
956
- const statusSize = args.bitsPerStatus;
957
1141
  const statusList = await import_vc_bitstring_status_lists.BitstreamStatusList.decode({
958
1142
  encodedList,
959
- statusSize
1143
+ statusSize: args.bitsPerStatus
960
1144
  });
961
1145
  const numIndex = typeof args.statusListIndex === "number" ? args.statusListIndex : parseInt(args.statusListIndex);
962
1146
  if (statusList.getLength() <= numIndex) {
@@ -964,67 +1148,177 @@ var BitstringStatusListImplementation = class {
964
1148
  }
965
1149
  return statusList.getStatus(numIndex);
966
1150
  }
967
- async toStatusListDetails(args) {
968
- const { statusListPayload, bitsPerStatus } = args;
969
- if (!bitsPerStatus || bitsPerStatus < 1) {
970
- return Promise.reject("bitsPerStatus must be set for bitstring status lists and must be 1 or higher. (toStatusListDetails)");
971
- }
972
- 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);
973
1158
  const { issuer, credentialSubject } = uniform;
974
- const id = getAssertedValue("id", uniform.id);
975
- const encodedList = getAssertedProperty("encodedList", credentialSubject);
976
- const proofFormat = import_ssi_types5.CredentialMapper.detectDocumentType(statusListPayload) === import_ssi_types5.DocumentFormat.JWT ? "jwt" : "lds";
977
- const credSubject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
978
- const statusPurpose = getAssertedProperty("statusPurpose", credSubject);
979
- const validFrom = uniform.validFrom ? new Date(uniform.validFrom) : void 0;
980
- const validUntil = uniform.validUntil ? new Date(uniform.validUntil) : void 0;
981
- const ttl = credSubject.ttl;
982
- const statuslistLength = import_vc_bitstring_status_lists.BitstreamStatusList.getStatusListLength(encodedList, bitsPerStatus);
1159
+ const subject = Array.isArray(credentialSubject) ? credentialSubject[0] : credentialSubject;
983
1160
  return {
984
- id,
985
- encodedList,
1161
+ id: getAssertedValue("id", uniform.id),
986
1162
  issuer,
987
- type: import_ssi_types5.StatusListType.BitstringStatusList,
988
- proofFormat,
989
- length: statuslistLength,
990
- statusListCredential: statusListPayload,
991
- statuslistContentType: this.buildContentType(proofFormat),
992
- 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,
993
1194
  statusPurpose,
994
1195
  bitsPerStatus,
995
- validFrom,
996
- validUntil,
997
- ttl
998
- },
999
- ...args.correlationId && {
1000
- correlationId: args.correlationId
1001
- },
1002
- ...args.driverType && {
1003
- 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"));
1004
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
1005
1284
  };
1006
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
+ */
1007
1293
  async createVerifiableCredential(args, context) {
1294
+ const { unsignedCredential, issuer, proofFormat, keyRef } = args;
1008
1295
  const identifier = await context.agent.identifierManagedGet({
1009
- identifier: typeof args.issuer === "string" ? args.issuer : args.issuer.id,
1296
+ identifier: typeof issuer === "string" ? issuer : issuer.id,
1010
1297
  vmRelationship: "assertionMethod",
1011
1298
  offlineWhenNoDIDRegistered: true
1012
1299
  });
1013
- const unsignedCredential = await (0, import_vc_bitstring_status_lists.createStatusListCredential)(args);
1014
1300
  const verifiableCredential = await context.agent.createVerifiableCredential({
1015
1301
  credential: unsignedCredential,
1016
- keyRef: args.keyRef ?? identifier.kmsKeyRef,
1017
- proofFormat: args.proofFormat,
1302
+ keyRef: keyRef ?? identifier.kmsKeyRef,
1303
+ proofFormat,
1018
1304
  fetchRemoteContexts: true
1019
1305
  });
1020
1306
  return import_ssi_types5.CredentialMapper.toWrappedVerifiableCredential(verifiableCredential).original;
1021
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
+ */
1022
1314
  buildContentType(proofFormat) {
1023
1315
  switch (proofFormat) {
1024
1316
  case "jwt":
1025
- return `application/statuslist+jwt`;
1317
+ return "application/statuslist+jwt";
1026
1318
  case "cbor":
1027
- return `application/statuslist+cwt`;
1319
+ return "application/statuslist+cwt";
1320
+ case "vc+jwt":
1321
+ return "application/statuslist+vc+jwt";
1028
1322
  case "lds":
1029
1323
  return "application/statuslist+ld+json";
1030
1324
  default:
@@ -1180,36 +1474,35 @@ async function updateStatusIndexFromStatusListCredential(args, context) {
1180
1474
  return implementation.updateStatusListIndex(args, context);
1181
1475
  }
1182
1476
  __name(updateStatusIndexFromStatusListCredential, "updateStatusIndexFromStatusListCredential");
1183
- async function statusListCredentialToDetails({ correlationId, driverType, statusListCredential, bitsPerStatus }) {
1184
- const credential = getAssertedValue("statusListCredential", statusListCredential);
1185
- let statusListType;
1186
- const documentFormat = import_ssi_types7.CredentialMapper.detectDocumentType(credential);
1187
- if (documentFormat === import_ssi_types7.DocumentFormat.JWT) {
1188
- const [header] = credential.split(".");
1189
- const decodedHeader = JSON.parse(Buffer.from(header, "base64").toString());
1190
- if (decodedHeader.typ === "statuslist+jwt") {
1191
- statusListType = import_ssi_types7.StatusListType.OAuthStatusList;
1192
- }
1193
- } else if (documentFormat === import_ssi_types7.DocumentFormat.MSO_MDOC) {
1194
- statusListType = import_ssi_types7.StatusListType.OAuthStatusList;
1195
- }
1196
- if (!statusListType) {
1197
- const uniform = import_ssi_types7.CredentialMapper.toUniformCredential(credential);
1198
- const type = uniform.type.find((t) => t.includes("StatusList2021") || t.includes("OAuth2StatusList") || t.includes("BitstringStatusList"));
1199
- if (!type) {
1200
- throw new Error("Invalid status list credential type");
1201
- }
1202
- 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);
1203
1492
  }
1493
+ }
1494
+ __name(toStatusListDetails, "toStatusListDetails");
1495
+ async function createCredentialStatusFromStatusList(args) {
1496
+ const { statusList, statusListEntry, statusListIndex } = args;
1497
+ const statusListType = determineStatusListType(statusList.statusListCredential);
1204
1498
  const implementation = getStatusListImplementation(statusListType);
1205
- return await implementation.toStatusListDetails({
1206
- statusListPayload: credential,
1207
- correlationId,
1208
- driverType,
1209
- bitsPerStatus
1499
+ return implementation.createCredentialStatus({
1500
+ statusList,
1501
+ statusListEntry,
1502
+ statusListIndex
1210
1503
  });
1211
1504
  }
1212
- __name(statusListCredentialToDetails, "statusListCredentialToDetails");
1505
+ __name(createCredentialStatusFromStatusList, "createCredentialStatusFromStatusList");
1213
1506
  async function updateStatusListIndexFromEncodedList(args, context) {
1214
1507
  const { type } = getAssertedValue("type", args);
1215
1508
  const implementation = getStatusListImplementation(type);