@sphereon/ssi-sdk.vc-status-list 0.34.1-next.7 → 0.34.1-next.85

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.
@@ -1,31 +1,26 @@
1
1
  import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
2
2
  import {
3
+ type CredentialProofFormat,
3
4
  type ICredential,
4
5
  type ICredentialStatus,
5
6
  type IIssuer,
6
7
  type IVerifiableCredential,
7
8
  type OrPromise,
8
- type CredentialProofFormat,
9
9
  type StatusListCredential,
10
- StatusListCredentialIdMode,
11
10
  StatusListDriverType,
12
11
  type StatusListIndexingDirection,
13
12
  StatusListType,
14
13
  type StatusPurpose2021,
15
14
  } from '@sphereon/ssi-types'
16
- import type {
17
- CredentialPayload,
18
- IAgentContext,
19
- ICredentialIssuer,
20
- ICredentialPlugin,
21
- ICredentialVerifier,
22
- IKeyManager,
23
- IPluginMethodMap,
24
- } from '@veramo/core'
15
+ import type { CredentialPayload, IAgentContext, ICredentialIssuer, ICredentialVerifier, IKeyManager, IPluginMethodMap } from '@veramo/core'
25
16
  import { DataSource } from 'typeorm'
26
17
  import type { BitsPerStatus } from '@sd-jwt/jwt-status-list'
27
18
  import type { SdJwtVcPayload } from '@sd-jwt/sd-jwt-vc'
28
19
  import type { StatusListOpts } from '@sphereon/oid4vci-common'
20
+ import { BitstringStatusPurpose } from '@4sure-tech/vc-bitstring-status-lists'
21
+ import { IVcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'
22
+ import { IExtractedCredentialDetails } from '../impl/IStatusList'
23
+ import { BitstringStatusListArgs, IStatusListEntity } from '@sphereon/ssi-sdk.data-store'
29
24
 
30
25
  export enum StatusOAuth {
31
26
  Valid = 0,
@@ -45,7 +40,7 @@ export type StatusList2021Args = {
45
40
  }
46
41
 
47
42
  export type OAuthStatusListArgs = {
48
- bitsPerStatus?: BitsPerStatus
43
+ bitsPerStatus: BitsPerStatus
49
44
  expiresAt?: Date
50
45
  }
51
46
 
@@ -59,6 +54,7 @@ export type BaseCreateNewStatusListArgs = {
59
54
  keyRef?: string
60
55
  statusList2021?: StatusList2021Args
61
56
  oauthStatusList?: OAuthStatusListArgs
57
+ bitstringStatusList?: BitstringStatusListArgs
62
58
  driverType?: StatusListDriverType
63
59
  }
64
60
 
@@ -71,10 +67,18 @@ export type UpdateOAuthStatusListArgs = {
71
67
  expiresAt?: Date
72
68
  }
73
69
 
70
+ export type UpdateBitstringStatusListArgs = {
71
+ statusPurpose: BitstringStatusPurpose
72
+ bitsPerStatus: number
73
+ validFrom?: Date
74
+ validUntil?: Date
75
+ ttl?: number
76
+ }
77
+
74
78
  export interface UpdateStatusListFromEncodedListArgs {
75
79
  type?: StatusListType
76
80
  statusListIndex: number | string
77
- value: boolean
81
+ value: number
78
82
  proofFormat?: CredentialProofFormat
79
83
  keyRef?: string
80
84
  correlationId?: string
@@ -83,6 +87,7 @@ export interface UpdateStatusListFromEncodedListArgs {
83
87
  id: string
84
88
  statusList2021?: UpdateStatusList2021Args
85
89
  oauthStatusList?: UpdateOAuthStatusListArgs
90
+ bitstringStatusList?: UpdateBitstringStatusListArgs
86
91
  }
87
92
 
88
93
  export interface UpdateStatusListFromStatusListCredentialArgs {
@@ -93,31 +98,32 @@ export interface UpdateStatusListFromStatusListCredentialArgs {
93
98
  }
94
99
 
95
100
  export interface StatusListResult {
101
+ id: string
96
102
  encodedList: string
97
- statusListCredential: StatusListCredential
98
- length: number
103
+ issuer: string | IIssuer
99
104
  type: StatusListType
100
105
  proofFormat: CredentialProofFormat
101
- id: string
106
+ length: number
107
+ statusListCredential: StatusListCredential
102
108
  statuslistContentType: string
103
- issuer: string | IIssuer
104
- statusList2021?: StatusList2021Details
105
- oauthStatusList?: OAuthStatusDetails
106
-
107
- // These cannot be deduced from the VC, so they are present when callers pass in these values as params
108
109
  correlationId?: string
109
110
  driverType?: StatusListDriverType
110
- credentialIdMode?: StatusListCredentialIdMode
111
- }
112
-
113
- interface StatusList2021Details {
114
- indexingDirection: StatusListIndexingDirection
115
- statusPurpose?: StatusPurpose2021
116
- }
117
111
 
118
- interface OAuthStatusDetails {
119
- bitsPerStatus?: BitsPerStatus
120
- expiresAt?: Date
112
+ statusList2021?: {
113
+ indexingDirection: StatusListIndexingDirection
114
+ statusPurpose: StatusPurpose2021
115
+ }
116
+ oauthStatusList?: {
117
+ bitsPerStatus: number
118
+ expiresAt?: Date
119
+ }
120
+ bitstringStatusList?: {
121
+ statusPurpose: BitstringStatusPurpose | BitstringStatusPurpose[]
122
+ bitsPerStatus?: number
123
+ validFrom?: Date
124
+ validUntil?: Date
125
+ ttl?: number
126
+ }
121
127
  }
122
128
 
123
129
  export interface StatusList2021EntryCredentialStatus extends ICredentialStatus {
@@ -154,12 +160,14 @@ export interface CreateStatusListArgs {
154
160
  length?: number
155
161
  statusList2021?: StatusList2021Args
156
162
  oauthStatusList?: OAuthStatusListArgs
163
+ bitstringStatusList?: BitstringStatusListArgs
157
164
  }
158
165
 
159
166
  export interface UpdateStatusListIndexArgs {
160
167
  statusListCredential: StatusListCredential // | CompactJWT
161
168
  statusListIndex: number | string
162
169
  value: number | Status2021 | StatusOAuth
170
+ bitsPerStatus?: number
163
171
  keyRef?: string
164
172
  expiresAt?: Date
165
173
  }
@@ -167,14 +175,27 @@ export interface UpdateStatusListIndexArgs {
167
175
  export interface CheckStatusIndexArgs {
168
176
  statusListCredential: StatusListCredential // | CompactJWT
169
177
  statusListIndex: string | number
178
+ bitsPerStatus?: number
170
179
  }
171
180
 
172
- export interface ToStatusListDetailsArgs {
173
- statusListPayload: StatusListCredential
181
+ // For the CREATE and READ contexts
182
+ export interface IToDetailsFromCredentialArgs {
183
+ // The source credential we are converting
184
+ statusListCredential: StatusListCredential
185
+
186
+ // The required metadata that is NOT in the credential itself
187
+ statusListType: StatusListType
188
+ bitsPerStatus?: number
174
189
  correlationId?: string
175
190
  driverType?: StatusListDriverType
176
191
  }
177
192
 
193
+ // For the UPDATE context
194
+ export interface IMergeDetailsWithEntityArgs {
195
+ extractedDetails: IExtractedCredentialDetails
196
+ statusListEntity: IStatusListEntity
197
+ }
198
+
178
199
  /**
179
200
  * The interface definition for a plugin that can add statuslist info to a credential
180
201
  *
@@ -260,5 +281,5 @@ export type SignedStatusListData = {
260
281
  encodedList: string
261
282
  }
262
283
 
263
- export type IRequiredPlugins = ICredentialPlugin & IIdentifierResolution
264
- export type IRequiredContext = IAgentContext<ICredentialIssuer & ICredentialVerifier & IIdentifierResolution & IKeyManager & ICredentialPlugin>
284
+ export type IRequiredPlugins = IVcdmCredentialPlugin & IIdentifierResolution
285
+ export type IRequiredContext = IAgentContext<ICredentialIssuer & ICredentialVerifier & IIdentifierResolution & IKeyManager & IVcdmCredentialPlugin>
package/src/utils.ts CHANGED
@@ -11,7 +11,7 @@ import { jwtDecode } from 'jwt-decode'
11
11
 
12
12
  export function getAssertedStatusListType(type?: StatusListType) {
13
13
  const assertedType = type ?? StatusListType.StatusList2021
14
- if (![StatusListType.StatusList2021, StatusListType.OAuthStatusList].includes(assertedType)) {
14
+ if (![StatusListType.StatusList2021, StatusListType.OAuthStatusList, StatusListType.BitstringStatusList].includes(assertedType)) {
15
15
  throw Error(`StatusList type ${assertedType} is not supported (yet)`)
16
16
  }
17
17
  return assertedType
@@ -39,8 +39,9 @@ export function getAssertedProperty<T extends object>(propertyName: string, obj:
39
39
  }
40
40
 
41
41
  const ValidProofTypeMap = new Map<StatusListType, CredentialProofFormat[]>([
42
- [StatusListType.StatusList2021, ['jwt', 'lds', 'EthereumEip712Signature2021']],
42
+ [StatusListType.StatusList2021, ['jwt', 'lds']],
43
43
  [StatusListType.OAuthStatusList, ['jwt', 'cbor']],
44
+ [StatusListType.BitstringStatusList, ['lds', 'vc+jwt']],
44
45
  ])
45
46
 
46
47
  export function assertValidProofType(type: StatusListType, proofFormat: CredentialProofFormat) {
@@ -52,31 +53,60 @@ export function assertValidProofType(type: StatusListType, proofFormat: Credenti
52
53
 
53
54
  export function determineStatusListType(credential: StatusListCredential): StatusListType {
54
55
  const proofFormat = determineProofFormat(credential)
56
+
55
57
  switch (proofFormat) {
56
58
  case 'jwt':
57
- const payload: StatusListCredential = jwtDecode(credential as string)
58
- const keys = Object.keys(payload)
59
- if (keys.includes('status_list')) {
60
- return StatusListType.OAuthStatusList
61
- } else if (keys.includes('vc')) {
62
- return StatusListType.StatusList2021
63
- }
64
- break
59
+ return determineJwtStatusListType(credential as string)
65
60
  case 'lds':
66
- const uniform = CredentialMapper.toUniformCredential(credential)
67
- const type = uniform.type.find((t) => {
68
- return Object.values(StatusListType).some((statusType) => t.includes(statusType))
69
- })
70
- if (!type) {
71
- throw new Error('Invalid status list credential type')
72
- }
73
- return type.replace('Credential', '') as StatusListType
74
-
61
+ return determineLdsStatusListType(credential)
75
62
  case 'cbor':
76
63
  return StatusListType.OAuthStatusList
64
+ default:
65
+ throw new Error('Cannot determine status list type from credential payload')
66
+ }
67
+ }
68
+
69
+ function determineJwtStatusListType(credential: string): StatusListType {
70
+ const payload: any = jwtDecode(credential)
71
+
72
+ // OAuth status list format
73
+ if ('status_list' in payload) {
74
+ return StatusListType.OAuthStatusList
75
+ }
76
+
77
+ // Direct credential subject
78
+ if ('credentialSubject' in payload) {
79
+ return getStatusListTypeFromSubject(payload.credentialSubject)
80
+ }
81
+
82
+ // Wrapped VC format
83
+ if ('vc' in payload && 'credentialSubject' in payload.vc) {
84
+ return getStatusListTypeFromSubject(payload.vc.credentialSubject)
85
+ }
86
+
87
+ throw new Error('Invalid status list credential: credentialSubject not found')
88
+ }
89
+
90
+ function determineLdsStatusListType(credential: StatusListCredential): StatusListType {
91
+ const uniform = CredentialMapper.toUniformCredential(credential)
92
+ const statusListType = uniform.type.find((type) => Object.values(StatusListType).some((statusType) => type.includes(statusType)))
93
+
94
+ if (!statusListType) {
95
+ throw new Error('Invalid status list credential type')
77
96
  }
78
97
 
79
- throw new Error('Cannot determine status list type from credential payload')
98
+ return statusListType.replace('Credential', '') as StatusListType
99
+ }
100
+
101
+ function getStatusListTypeFromSubject(credentialSubject: any): StatusListType {
102
+ switch (credentialSubject.type) {
103
+ case 'StatusList2021':
104
+ return StatusListType.StatusList2021
105
+ case 'BitstringStatusList':
106
+ return StatusListType.BitstringStatusList
107
+ default:
108
+ throw new Error(`Unknown credential subject type: ${credentialSubject.type}`)
109
+ }
80
110
  }
81
111
 
82
112
  export function determineProofFormat(credential: StatusListCredential): CredentialProofFormat {
@@ -93,3 +123,35 @@ export function determineProofFormat(credential: StatusListCredential): Credenti
93
123
  throw Error('Cannot determine credential payload type')
94
124
  }
95
125
  }
126
+
127
+ /**
128
+ * Ensures a value is converted to a Date object if it's a valid date string,
129
+ * otherwise returns the original value or undefined
130
+ *
131
+ * @param value - The value to convert to Date (can be Date, string, or undefined)
132
+ * @returns Date object, undefined, or the original value if conversion fails
133
+ */
134
+ export function ensureDate(value: Date | string | undefined): Date | undefined {
135
+ if (value === undefined || value === null) {
136
+ return undefined
137
+ }
138
+
139
+ if (value instanceof Date) {
140
+ return value
141
+ }
142
+
143
+ if (typeof value === 'string') {
144
+ if (value.trim() === '') {
145
+ return undefined
146
+ }
147
+
148
+ const date = new Date(value)
149
+ // Check if the date is valid
150
+ if (isNaN(date.getTime())) {
151
+ return undefined
152
+ }
153
+ return date
154
+ }
155
+
156
+ return undefined
157
+ }