dcql 0.4.3-alpha-20250706143223 → 0.5.0-alpha-20250724114402
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.d.mts +3565 -2482
- package/dist/index.d.ts +3565 -2482
- package/dist/index.js +109 -85
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +109 -85
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
@@ -113,10 +113,19 @@ import * as v2 from "valibot";
|
|
113
113
|
// src/u-dcql.ts
|
114
114
|
import * as v from "valibot";
|
115
115
|
var idRegex = /^[a-zA-Z0-9_-]+$/;
|
116
|
+
function asNonEmptyArrayOrUndefined(array8) {
|
117
|
+
return array8.length > 0 ? array8 : void 0;
|
118
|
+
}
|
119
|
+
function isNonEmptyArray(array8) {
|
120
|
+
return array8.length > 0;
|
121
|
+
}
|
116
122
|
var vNonEmptyArray = (item) => {
|
117
123
|
return v.pipe(
|
118
|
-
v.array(item),
|
119
|
-
v.custom(
|
124
|
+
v.array(item, (i) => `Expected input to be an array, but received '${i.received}'`),
|
125
|
+
v.custom(
|
126
|
+
(input) => input.length > 0,
|
127
|
+
"Array must be non-empty and have length of at least 1"
|
128
|
+
)
|
120
129
|
);
|
121
130
|
};
|
122
131
|
var vIncludesAll = (subset) => {
|
@@ -191,60 +200,71 @@ var vStringToJson = v.rawTransform(({ dataset, addIssue, NEVER }) => {
|
|
191
200
|
});
|
192
201
|
|
193
202
|
// src/dcql-query/m-dcql-trusted-authorities.ts
|
194
|
-
var getTrustedAuthorityParser = (trustedAuthority) => v2.
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
value: v2.union(
|
201
|
-
trustedAuthority.values.map(
|
202
|
-
(value) => v2.literal(
|
203
|
-
value,
|
204
|
-
(i) => `Expected trusted authority value to be '${value}' but received ${typeof i.input === "string" ? `'${i.input}'` : i.input}`
|
205
|
-
)
|
203
|
+
var getTrustedAuthorityParser = (trustedAuthority) => v2.pipe(
|
204
|
+
v2.object(
|
205
|
+
{
|
206
|
+
type: v2.literal(
|
207
|
+
trustedAuthority.type,
|
208
|
+
(i) => `Expected trusted authority type to be '${trustedAuthority.type}' but received ${typeof i.input === "string" ? `'${i.input}'` : i.input}`
|
206
209
|
),
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
210
|
+
// Some trusted authorities support an array as input type
|
211
|
+
values: v2.pipe(
|
212
|
+
vNonEmptyArray(v2.string()),
|
213
|
+
v2.someItem(
|
214
|
+
(item) => trustedAuthority.values.includes(item),
|
215
|
+
(i) => `Expected one of the trusted authority values to be '${trustedAuthority.values.join("' | '")}' but received '${i.input.join("' , '")}'`
|
216
|
+
)
|
217
|
+
)
|
218
|
+
},
|
219
|
+
`Expected trusted authority object with type '${trustedAuthority.type}' to be defined, but received undefined`
|
220
|
+
),
|
221
|
+
v2.transform(({ values, ...rest }) => ({
|
222
|
+
...rest,
|
223
|
+
value: values.find((value) => trustedAuthority.values.includes(value))
|
224
|
+
}))
|
211
225
|
);
|
212
226
|
var vAuthorityKeyIdentifier = v2.object({
|
213
227
|
type: v2.literal("aki"),
|
214
|
-
|
215
|
-
v2.
|
216
|
-
|
217
|
-
|
218
|
-
|
228
|
+
values: vNonEmptyArray(
|
229
|
+
v2.pipe(
|
230
|
+
v2.string("aki trusted authority value must be a string"),
|
231
|
+
vBase64url,
|
232
|
+
v2.description(
|
233
|
+
"Contains a list of KeyIdentifier entries of the AuthorityKeyIdentifier as defined in Section 4.2.1.1 of [RFC5280], encoded as base64url. The raw byte representation of one of the elements MUST match with the AuthorityKeyIdentifier element of an X.509 certificate in the certificate chain present in the credential (e.g., in the header of an mdoc or SD-JWT). Note that the chain can consist of a single certificate and the credential can include the entire X.509 chain or parts of it."
|
234
|
+
)
|
219
235
|
)
|
220
236
|
)
|
221
237
|
});
|
222
238
|
var vEtsiTrustedList = v2.object({
|
223
239
|
type: v2.literal("etsi_tl"),
|
224
|
-
|
225
|
-
v2.
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
240
|
+
values: vNonEmptyArray(
|
241
|
+
v2.pipe(
|
242
|
+
v2.string("etsi_tl trusted authority value must be a string"),
|
243
|
+
v2.url("etsi_tl trusted authority value must be a valid https url"),
|
244
|
+
v2.check(
|
245
|
+
(url2) => url2.startsWith("http://") || url2.startsWith("https://"),
|
246
|
+
"etsi_tl trusted authority value must be a valid https url"
|
247
|
+
),
|
248
|
+
v2.description(
|
249
|
+
"The identifier of a Trusted List as specified in ETSI TS 119 612 [ETSI.TL]. An ETSI Trusted List contains references to other Trusted Lists, creating a list of trusted lists, or entries for Trust Service Providers with corresponding service description and X.509 Certificates. The trust chain of a matching Credential MUST contain at least one X.509 Certificate that matches one of the entries of the Trusted List or its cascading Trusted Lists."
|
250
|
+
)
|
233
251
|
)
|
234
252
|
)
|
235
253
|
});
|
236
254
|
var vOpenidFederation = v2.object({
|
237
255
|
type: v2.literal("openid_federation"),
|
238
|
-
|
239
|
-
v2.
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
256
|
+
values: vNonEmptyArray(
|
257
|
+
v2.pipe(
|
258
|
+
v2.string("openid_federation trusted authority value must be a string"),
|
259
|
+
v2.url("openid_federation trusted authority value must be a valid https url"),
|
260
|
+
// TODO: should we have a config similar to oid4vc-ts to support http for development?
|
261
|
+
v2.check(
|
262
|
+
(url2) => url2.startsWith("http://") || url2.startsWith("https://"),
|
263
|
+
"openid_federation trusted authority value must be a valid https url"
|
264
|
+
),
|
265
|
+
v2.description(
|
266
|
+
"The Entity Identifier as defined in Section 1 of [OpenID.Federation] that is bound to an entity in a federation. While this Entity Identifier could be any entity in that ecosystem, this entity would usually have the Entity Configuration of a Trust Anchor. A valid trust path, including the given Entity Identifier, must be constructible from a matching credential."
|
267
|
+
)
|
248
268
|
)
|
249
269
|
)
|
250
270
|
});
|
@@ -260,7 +280,7 @@ var DcqlTrustedAuthoritiesQuery;
|
|
260
280
|
)
|
261
281
|
),
|
262
282
|
values: v2.pipe(
|
263
|
-
vNonEmptyArray(authority.entries.
|
283
|
+
vNonEmptyArray(authority.entries.values.item),
|
264
284
|
v2.description(
|
265
285
|
"REQUIRED. An array of strings, where each string (value) contains information specific to the used Trusted Authorities Query type that allows to identify an issuer, trust framework, or a federation that an issuer belongs to."
|
266
286
|
)
|
@@ -646,17 +666,17 @@ var runClaimsQuery = (credentialQuery, ctx) => {
|
|
646
666
|
if (!credentialQuery.claims) {
|
647
667
|
return {
|
648
668
|
success: true,
|
649
|
-
valid_claims:
|
650
|
-
failed_claims:
|
669
|
+
valid_claims: void 0,
|
670
|
+
failed_claims: void 0,
|
651
671
|
valid_claim_sets: [
|
652
672
|
{
|
653
673
|
claim_set_index: void 0,
|
654
674
|
output: {},
|
655
675
|
success: true,
|
656
|
-
valid_claim_indexes:
|
676
|
+
valid_claim_indexes: void 0
|
657
677
|
}
|
658
678
|
],
|
659
|
-
failed_claim_sets:
|
679
|
+
failed_claim_sets: void 0
|
660
680
|
};
|
661
681
|
}
|
662
682
|
const failedClaims = [];
|
@@ -708,7 +728,7 @@ var runClaimsQuery = (credentialQuery, ctx) => {
|
|
708
728
|
success: true,
|
709
729
|
claim_set_index: claimSetIndex,
|
710
730
|
output,
|
711
|
-
valid_claim_indexes: claims.map((claim) => claim.claim_index)
|
731
|
+
valid_claim_indexes: asNonEmptyArrayOrUndefined(claims.map((claim) => claim.claim_index))
|
712
732
|
});
|
713
733
|
} else {
|
714
734
|
const issues = failedClaims.reduce((merged, claim) => deepMerge(claim.issues, merged), {});
|
@@ -717,24 +737,26 @@ var runClaimsQuery = (credentialQuery, ctx) => {
|
|
717
737
|
issues,
|
718
738
|
claim_set_index: claimSetIndex,
|
719
739
|
failed_claim_indexes: claims.filter((claim) => !claim.success).map((claim) => claim.claim_index),
|
720
|
-
valid_claim_indexes:
|
740
|
+
valid_claim_indexes: asNonEmptyArrayOrUndefined(
|
741
|
+
claims.filter((claim) => claim.success).map((claim) => claim.claim_index)
|
742
|
+
)
|
721
743
|
});
|
722
744
|
}
|
723
745
|
}
|
724
|
-
if (validClaimSets
|
746
|
+
if (isNonEmptyArray(validClaimSets)) {
|
725
747
|
return {
|
726
|
-
success:
|
727
|
-
failed_claim_sets: failedClaimSets,
|
728
|
-
|
729
|
-
valid_claims: validClaims.map(({ parser, ...rest }) => rest)
|
748
|
+
success: true,
|
749
|
+
failed_claim_sets: asNonEmptyArrayOrUndefined(failedClaimSets),
|
750
|
+
valid_claim_sets: validClaimSets,
|
751
|
+
valid_claims: asNonEmptyArrayOrUndefined(validClaims.map(({ parser, ...rest }) => rest)),
|
752
|
+
failed_claims: asNonEmptyArrayOrUndefined(failedClaims.map(({ parser, ...rest }) => rest))
|
730
753
|
};
|
731
754
|
}
|
732
755
|
return {
|
733
|
-
success:
|
756
|
+
success: false,
|
734
757
|
failed_claim_sets: failedClaimSets,
|
735
|
-
|
736
|
-
valid_claims: validClaims.map(({ parser, ...rest }) => rest)
|
737
|
-
failed_claims: failedClaims.map(({ parser, ...rest }) => rest)
|
758
|
+
failed_claims: failedClaims.map(({ parser, ...rest }) => rest),
|
759
|
+
valid_claims: asNonEmptyArrayOrUndefined(validClaims.map(({ parser, ...rest }) => rest))
|
738
760
|
};
|
739
761
|
};
|
740
762
|
|
@@ -839,7 +861,7 @@ var runTrustedAuthoritiesQuery = (credentialQuery, credential) => {
|
|
839
861
|
trusted_authority_index: trustedAuthorityIndex,
|
840
862
|
output: parseResult.output
|
841
863
|
},
|
842
|
-
failed_trusted_authorities: failedTrustedAuthorities
|
864
|
+
failed_trusted_authorities: asNonEmptyArrayOrUndefined(failedTrustedAuthorities)
|
843
865
|
};
|
844
866
|
}
|
845
867
|
const issues = v9.flatten(parseResult.issues);
|
@@ -859,12 +881,6 @@ var runTrustedAuthoritiesQuery = (credentialQuery, credential) => {
|
|
859
881
|
// src/dcql-parser/dcql-credential-query-result.ts
|
860
882
|
var runCredentialQuery = (credentialQuery, ctx) => {
|
861
883
|
const { credentials, presentation } = ctx;
|
862
|
-
if (ctx.credentials.length === 0) {
|
863
|
-
throw new DcqlError({
|
864
|
-
message: "Credentials array provided to credential query has length of 0, unable to match credentials against credential query.",
|
865
|
-
code: "BAD_REQUEST"
|
866
|
-
});
|
867
|
-
}
|
868
884
|
const validCredentials = [];
|
869
885
|
const failedCredentials = [];
|
870
886
|
for (const [credentialIndex, credential] of credentials.entries()) {
|
@@ -889,21 +905,20 @@ var runCredentialQuery = (credentialQuery, ctx) => {
|
|
889
905
|
});
|
890
906
|
}
|
891
907
|
}
|
892
|
-
if (
|
908
|
+
if (isNonEmptyArray(validCredentials)) {
|
893
909
|
return {
|
894
|
-
success:
|
910
|
+
success: true,
|
895
911
|
credential_query_id: credentialQuery.id,
|
896
|
-
|
897
|
-
|
898
|
-
valid_credentials: void 0
|
912
|
+
failed_credentials: asNonEmptyArrayOrUndefined(failedCredentials),
|
913
|
+
valid_credentials: validCredentials
|
899
914
|
};
|
900
915
|
}
|
901
916
|
return {
|
902
|
-
success:
|
917
|
+
success: false,
|
903
918
|
credential_query_id: credentialQuery.id,
|
904
|
-
|
905
|
-
|
906
|
-
valid_credentials:
|
919
|
+
// Can be undefined if no credentials were provided to the query
|
920
|
+
failed_credentials: asNonEmptyArrayOrUndefined(failedCredentials),
|
921
|
+
valid_credentials: void 0
|
907
922
|
};
|
908
923
|
};
|
909
924
|
|
@@ -1094,7 +1109,7 @@ var DcqlClaimsResult;
|
|
1094
1109
|
claim_set_index: v12.union([v12.number(), v12.undefined()]),
|
1095
1110
|
// We use indexes because if there are no claim sets, the ids can be undefined
|
1096
1111
|
// Can be empty array in case there are no claims
|
1097
|
-
valid_claim_indexes: v12.
|
1112
|
+
valid_claim_indexes: v12.optional(vNonEmptyArray(v12.number())),
|
1098
1113
|
failed_claim_indexes: v12.optional(v12.undefined()),
|
1099
1114
|
output: vClaimsOutput
|
1100
1115
|
});
|
@@ -1103,20 +1118,20 @@ var DcqlClaimsResult;
|
|
1103
1118
|
// Undefined in case of no claim set
|
1104
1119
|
claim_set_index: v12.union([v12.number(), v12.undefined()]),
|
1105
1120
|
// We use indexes because if there are no claim sets, the ids can be undefined
|
1106
|
-
valid_claim_indexes: v12.
|
1121
|
+
valid_claim_indexes: v12.optional(vNonEmptyArray(v12.number())),
|
1107
1122
|
failed_claim_indexes: vNonEmptyArray(v12.number()),
|
1108
1123
|
issues: v12.record(v12.string(), v12.unknown())
|
1109
1124
|
});
|
1110
1125
|
DcqlClaimsResult2.vClaimsSuccessResult = v12.object({
|
1111
1126
|
success: v12.literal(true),
|
1112
|
-
valid_claims: v12.
|
1113
|
-
failed_claims: v12.
|
1127
|
+
valid_claims: v12.optional(vNonEmptyArray(DcqlClaimsResult2.vClaimsEntrySuccessResult)),
|
1128
|
+
failed_claims: v12.optional(vNonEmptyArray(DcqlClaimsResult2.vClaimsEntryFailureResult)),
|
1114
1129
|
valid_claim_sets: vNonEmptyArray(DcqlClaimsResult2.vClaimSetSuccessResult),
|
1115
|
-
failed_claim_sets: v12.
|
1130
|
+
failed_claim_sets: v12.optional(vNonEmptyArray(DcqlClaimsResult2.vClaimSetFailureResult))
|
1116
1131
|
});
|
1117
1132
|
DcqlClaimsResult2.vClaimsFailureResult = v12.object({
|
1118
1133
|
success: v12.literal(false),
|
1119
|
-
valid_claims: v12.
|
1134
|
+
valid_claims: v12.optional(vNonEmptyArray(DcqlClaimsResult2.vClaimsEntrySuccessResult)),
|
1120
1135
|
failed_claims: vNonEmptyArray(DcqlClaimsResult2.vClaimsEntryFailureResult),
|
1121
1136
|
valid_claim_sets: v12.optional(v12.undefined()),
|
1122
1137
|
failed_claim_sets: vNonEmptyArray(DcqlClaimsResult2.vClaimSetFailureResult)
|
@@ -1151,7 +1166,16 @@ var DcqlTrustedAuthoritiesResult;
|
|
1151
1166
|
DcqlTrustedAuthoritiesResult2.vTrustedAuthorityEntrySuccessResult = v14.object({
|
1152
1167
|
success: v14.literal(true),
|
1153
1168
|
trusted_authority_index: v14.number(),
|
1154
|
-
|
1169
|
+
// We map from values (multiple options for a credential/query) to value (the matching option)
|
1170
|
+
output: v14.variant(
|
1171
|
+
"type",
|
1172
|
+
DcqlCredentialTrustedAuthority.vModel.options.map(
|
1173
|
+
(o) => v14.object({
|
1174
|
+
type: o.entries.type,
|
1175
|
+
value: o.entries.values.item
|
1176
|
+
})
|
1177
|
+
)
|
1178
|
+
)
|
1155
1179
|
});
|
1156
1180
|
DcqlTrustedAuthoritiesResult2.vTrustedAuthorityEntryFailureResult = v14.object({
|
1157
1181
|
success: v14.literal(false),
|
@@ -1169,7 +1193,7 @@ var DcqlTrustedAuthoritiesResult;
|
|
1169
1193
|
v14.object({
|
1170
1194
|
success: v14.literal(true),
|
1171
1195
|
valid_trusted_authority: DcqlTrustedAuthoritiesResult2.vTrustedAuthorityEntrySuccessResult,
|
1172
|
-
failed_trusted_authorities: v14.
|
1196
|
+
failed_trusted_authorities: v14.optional(vNonEmptyArray(DcqlTrustedAuthoritiesResult2.vTrustedAuthorityEntryFailureResult))
|
1173
1197
|
})
|
1174
1198
|
]);
|
1175
1199
|
DcqlTrustedAuthoritiesResult2.vTrustedAuthorityFailureResult = v14.object({
|
@@ -1203,13 +1227,13 @@ var DcqlQueryResult;
|
|
1203
1227
|
success: v15.literal(true),
|
1204
1228
|
credential_query_id: vIdString,
|
1205
1229
|
valid_credentials: vNonEmptyArray(DcqlQueryResult2.vCredentialQueryItemCredentialSuccessResult),
|
1206
|
-
failed_credentials: v15.
|
1230
|
+
failed_credentials: v15.optional(vNonEmptyArray(DcqlQueryResult2.vCredentialQueryItemCredentialFailureResult))
|
1207
1231
|
}),
|
1208
1232
|
v15.object({
|
1209
1233
|
success: v15.literal(false),
|
1210
1234
|
credential_query_id: vIdString,
|
1211
1235
|
valid_credentials: v15.optional(v15.undefined()),
|
1212
|
-
failed_credentials: vNonEmptyArray(DcqlQueryResult2.vCredentialQueryItemCredentialFailureResult)
|
1236
|
+
failed_credentials: v15.optional(vNonEmptyArray(DcqlQueryResult2.vCredentialQueryItemCredentialFailureResult))
|
1213
1237
|
})
|
1214
1238
|
]);
|
1215
1239
|
DcqlQueryResult2.vCredentialQueryResult = v15.record(vIdString, DcqlQueryResult2.vCredentialQueryItemResult);
|
@@ -1285,7 +1309,7 @@ var DcqlPresentationResult;
|
|
1285
1309
|
const dqclQueryMatched = (
|
1286
1310
|
// We require that all the submitted presentations match with the queries
|
1287
1311
|
// So we must have success for all queries, and we don't allow failed_credentials
|
1288
|
-
queriesResults.every((result) => result.success && result.failed_credentials
|
1312
|
+
queriesResults.every((result) => result.success && !result.failed_credentials) && (credentialSetResults ? credentialSetResults.every((set) => !set.required || set.matching_options) : (
|
1289
1313
|
// If not credential_sets are used, we require that at least every credential has a match
|
1290
1314
|
dcqlQuery.credentials.every(
|
1291
1315
|
(credentialQuery) => queriesResults.find((result) => result.credential_query_id === credentialQuery.id)?.success
|