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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,5 @@
1
1
  import type { IIdentifierResolution } from '@sphereon/ssi-sdk-ext.identifier-resolution'
2
2
  import {
3
- BitstringStatusPurpose,
4
3
  type CredentialProofFormat,
5
4
  type ICredential,
6
5
  type ICredentialStatus,
@@ -8,25 +7,20 @@ import {
8
7
  type IVerifiableCredential,
9
8
  type OrPromise,
10
9
  type StatusListCredential,
11
- StatusListCredentialIdMode,
12
10
  StatusListDriverType,
13
11
  type StatusListIndexingDirection,
14
12
  StatusListType,
15
13
  type StatusPurpose2021,
16
14
  } from '@sphereon/ssi-types'
17
- import type {
18
- CredentialPayload,
19
- IAgentContext,
20
- ICredentialIssuer,
21
- ICredentialPlugin,
22
- ICredentialVerifier,
23
- IKeyManager,
24
- IPluginMethodMap,
25
- } from '@veramo/core'
15
+ import type { CredentialPayload, IAgentContext, ICredentialIssuer, ICredentialVerifier, IKeyManager, IPluginMethodMap } from '@veramo/core'
26
16
  import { DataSource } from 'typeorm'
27
17
  import type { BitsPerStatus } from '@sd-jwt/jwt-status-list'
28
18
  import type { SdJwtVcPayload } from '@sd-jwt/sd-jwt-vc'
29
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'
30
24
 
31
25
  export enum StatusOAuth {
32
26
  Valid = 0,
@@ -39,20 +33,6 @@ export enum Status2021 {
39
33
  Invalid = 1,
40
34
  }
41
35
 
42
- export type BitstringStatus = {
43
- status: string
44
- message?: string
45
- [x: string]: any
46
- }
47
-
48
- export type BitstringStatusResult = BitstringStatus & {
49
- index: number
50
- status: string
51
- set: boolean
52
- message?: string
53
- [x: string]: any
54
- }
55
-
56
36
  export type StatusList2021Args = {
57
37
  indexingDirection: StatusListIndexingDirection
58
38
  statusPurpose?: StatusPurpose2021
@@ -60,19 +40,10 @@ export type StatusList2021Args = {
60
40
  }
61
41
 
62
42
  export type OAuthStatusListArgs = {
63
- bitsPerStatus?: BitsPerStatus
43
+ bitsPerStatus: BitsPerStatus
64
44
  expiresAt?: Date
65
45
  }
66
46
 
67
- export type BitstringStatusListArgs = {
68
- statusPurpose: BitstringStatusPurpose
69
- statusSize?: number
70
- statusMessage?: Array<BitstringStatus>
71
- ttl?: number
72
- validFrom?: Date
73
- validUntil?: Date
74
- }
75
-
76
47
  export type BaseCreateNewStatusListArgs = {
77
48
  type: StatusListType
78
49
  id: string
@@ -83,6 +54,7 @@ export type BaseCreateNewStatusListArgs = {
83
54
  keyRef?: string
84
55
  statusList2021?: StatusList2021Args
85
56
  oauthStatusList?: OAuthStatusListArgs
57
+ bitstringStatusList?: BitstringStatusListArgs
86
58
  driverType?: StatusListDriverType
87
59
  }
88
60
 
@@ -97,8 +69,7 @@ export type UpdateOAuthStatusListArgs = {
97
69
 
98
70
  export type UpdateBitstringStatusListArgs = {
99
71
  statusPurpose: BitstringStatusPurpose
100
- statusSize?: number
101
- statusMessage?: Array<BitstringStatus>
72
+ bitsPerStatus: number
102
73
  validFrom?: Date
103
74
  validUntil?: Date
104
75
  ttl?: number
@@ -107,7 +78,7 @@ export type UpdateBitstringStatusListArgs = {
107
78
  export interface UpdateStatusListFromEncodedListArgs {
108
79
  type?: StatusListType
109
80
  statusListIndex: number | string
110
- value: boolean
81
+ value: number
111
82
  proofFormat?: CredentialProofFormat
112
83
  keyRef?: string
113
84
  correlationId?: string
@@ -123,43 +94,36 @@ export interface UpdateStatusListFromStatusListCredentialArgs {
123
94
  statusListCredential: StatusListCredential // | CompactJWT
124
95
  keyRef?: string
125
96
  statusListIndex: number | string
126
- value: number | Status2021 | StatusOAuth | BitstringStatus
97
+ value: number | Status2021 | StatusOAuth
127
98
  }
128
99
 
129
100
  export interface StatusListResult {
101
+ id: string
130
102
  encodedList: string
131
- statusListCredential: StatusListCredential
132
- length: number
103
+ issuer: string | IIssuer
133
104
  type: StatusListType
134
105
  proofFormat: CredentialProofFormat
135
- id: string
106
+ length: number
107
+ statusListCredential: StatusListCredential
136
108
  statuslistContentType: string
137
- issuer: string | IIssuer
138
- statusList2021?: StatusList2021Details
139
- oauthStatusList?: OAuthStatusDetails
140
- bitstringStatusList?: BitstringStatusDetails
141
-
142
- // These cannot be deduced from the VC, so they are present when callers pass in these values as params
143
109
  correlationId?: string
144
110
  driverType?: StatusListDriverType
145
- credentialIdMode?: StatusListCredentialIdMode
146
- }
147
111
 
148
- interface StatusList2021Details {
149
- indexingDirection: StatusListIndexingDirection
150
- statusPurpose?: StatusPurpose2021
151
- }
152
-
153
- interface OAuthStatusDetails {
154
- bitsPerStatus?: BitsPerStatus
155
- expiresAt?: Date
156
- }
157
-
158
- interface BitstringStatusDetails {
159
- statusPurpose: BitstringStatusPurpose
160
- validFrom?: Date
161
- validUntil?: Date
162
- ttl?: number
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
+ }
163
127
  }
164
128
 
165
129
  export interface StatusList2021EntryCredentialStatus extends ICredentialStatus {
@@ -177,16 +141,6 @@ export interface StatusListOAuthEntryCredentialStatus extends ICredentialStatus
177
141
  expiresAt?: Date
178
142
  }
179
143
 
180
- export interface BitstringStatusListEntryCredentialStatus extends ICredentialStatus {
181
- type: 'BitstringStatusListEntry'
182
- statusPurpose: BitstringStatusPurpose | BitstringStatusPurpose[]
183
- statusListIndex: string
184
- statusListCredential: string
185
- statusSize?: number
186
- statusMessage?: Array<BitstringStatus>
187
- statusReference?: string | string[]
188
- }
189
-
190
144
  export interface StatusList2021ToVerifiableCredentialArgs {
191
145
  issuer: string | IIssuer
192
146
  id: string
@@ -212,7 +166,8 @@ export interface CreateStatusListArgs {
212
166
  export interface UpdateStatusListIndexArgs {
213
167
  statusListCredential: StatusListCredential // | CompactJWT
214
168
  statusListIndex: number | string
215
- value: number | Status2021 | StatusOAuth | BitstringStatus
169
+ value: number | Status2021 | StatusOAuth
170
+ bitsPerStatus?: number
216
171
  keyRef?: string
217
172
  expiresAt?: Date
218
173
  }
@@ -220,14 +175,27 @@ export interface UpdateStatusListIndexArgs {
220
175
  export interface CheckStatusIndexArgs {
221
176
  statusListCredential: StatusListCredential // | CompactJWT
222
177
  statusListIndex: string | number
178
+ bitsPerStatus?: number
223
179
  }
224
180
 
225
- export interface ToStatusListDetailsArgs {
226
- 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
227
189
  correlationId?: string
228
190
  driverType?: StatusListDriverType
229
191
  }
230
192
 
193
+ // For the UPDATE context
194
+ export interface IMergeDetailsWithEntityArgs {
195
+ extractedDetails: IExtractedCredentialDetails
196
+ statusListEntity: IStatusListEntity
197
+ }
198
+
231
199
  /**
232
200
  * The interface definition for a plugin that can add statuslist info to a credential
233
201
  *
@@ -313,5 +281,5 @@ export type SignedStatusListData = {
313
281
  encodedList: string
314
282
  }
315
283
 
316
- export type IRequiredPlugins = ICredentialPlugin & IIdentifierResolution
317
- 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
@@ -41,6 +41,7 @@ export function getAssertedProperty<T extends object>(propertyName: string, obj:
41
41
  const ValidProofTypeMap = new Map<StatusListType, CredentialProofFormat[]>([
42
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
+ }